@dbx-tools/projen 0.9.21 → 0.9.28

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 (108) hide show
  1. package/README.md +77 -207
  2. package/index.ts +10 -12
  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/databricks-cli-assets.ts +129 -0
  18. package/tasks/local-publish.ts +23 -107
  19. package/tasks/publish-npm.ts +10 -1
  20. package/tasks/publish-python.ts +26 -11
  21. package/tasks/publish.ts +12 -48
  22. package/tasks/python-node-bindings-watch.ts +47 -0
  23. package/tasks/python-node-bindings.ts +1017 -0
  24. package/tasks/python-release.ts +74 -0
  25. package/tasks/release.ts +99 -0
  26. package/tasks/sync.ts +13 -18
  27. package/tasks/version-check.ts +1 -28
  28. package/._LICENSE +0 -0
  29. package/._README.md +0 -0
  30. package/._index.ts +0 -0
  31. package/._package.json +0 -0
  32. package/src/.__lazy-require.ts +0 -0
  33. package/src/.__release-platform.ts +0 -0
  34. package/src/.__rust-project.ts +0 -0
  35. package/src/.__rust-release-workflow.ts +0 -0
  36. package/src/.__task-command.ts +0 -0
  37. package/src/._barrels.ts +0 -0
  38. package/src/._bun-app.ts +0 -0
  39. package/src/._bun-workflow.ts +0 -0
  40. package/src/._clean.ts +0 -0
  41. package/src/._codegen.ts +0 -0
  42. package/src/._dbx-tools-config.ts +0 -0
  43. package/src/._engine-root.ts +0 -0
  44. package/src/._generated.ts +0 -0
  45. package/src/._mixin.ts +0 -0
  46. package/src/._module-exports.ts +0 -0
  47. package/src/._openapi.ts +0 -0
  48. package/src/._packages.ts +0 -0
  49. package/src/._pnpm-workspace.ts +0 -0
  50. package/src/._project-js.ts +0 -0
  51. package/src/._project-predicate.ts +0 -0
  52. package/src/._project-py.ts +0 -0
  53. package/src/._project-rs.ts +0 -0
  54. package/src/._project.ts +0 -0
  55. package/src/._projen-version.ts +0 -0
  56. package/src/._publish.ts +0 -0
  57. package/src/._release-catalog.ts +0 -0
  58. package/src/._release-dispatch.ts +0 -0
  59. package/src/._release-github.ts +0 -0
  60. package/src/._release.ts +0 -0
  61. package/src/._scaffold.ts +0 -0
  62. package/src/._tags.ts +0 -0
  63. package/src/._tsconfig.ts +0 -0
  64. package/src/._uniffi.ts +0 -0
  65. package/src/._vscode.ts +0 -0
  66. package/src/._watch.ts +0 -0
  67. package/src/._workspace-lock.ts +0 -0
  68. package/src/._workspace-version.ts +0 -0
  69. package/src/_rust-project.ts +0 -429
  70. package/src/_rust-release-workflow.ts +0 -311
  71. package/src/project-rs.ts +0 -1054
  72. package/src/uniffi.ts +0 -65
  73. package/tasks/._barrels.ts +0 -0
  74. package/tasks/._bump.ts +0 -0
  75. package/tasks/._clean.ts +0 -0
  76. package/tasks/._compile-workspace.ts +0 -0
  77. package/tasks/._local-publish.ts +0 -0
  78. package/tasks/._openapi.ts +0 -0
  79. package/tasks/._projenrc.ts +0 -0
  80. package/tasks/._publish-npm.ts +0 -0
  81. package/tasks/._publish-python.ts +0 -0
  82. package/tasks/._publish-uniffi-local.ts +0 -0
  83. package/tasks/._publish.ts +0 -0
  84. package/tasks/._python-registry.ts +0 -0
  85. package/tasks/._release-assets.ts +0 -0
  86. package/tasks/._release-candidate.ts +0 -0
  87. package/tasks/._release-manifest.ts +0 -0
  88. package/tasks/._release-pr.ts +0 -0
  89. package/tasks/._release-summary.ts +0 -0
  90. package/tasks/._release-version.ts +0 -0
  91. package/tasks/._rust.ts +0 -0
  92. package/tasks/._sync.ts +0 -0
  93. package/tasks/._uniffi-python.d.ts +0 -0
  94. package/tasks/._uniffi-python.js +0 -0
  95. package/tasks/._uniffi-release.mjs +0 -0
  96. package/tasks/._uniffi.ts +0 -0
  97. package/tasks/._version-check.ts +0 -0
  98. package/tasks/publish-uniffi-local.ts +0 -359
  99. package/tasks/release-assets.ts +0 -467
  100. package/tasks/release-candidate.ts +0 -416
  101. package/tasks/release-manifest.ts +0 -273
  102. package/tasks/release-pr.ts +0 -589
  103. package/tasks/release-summary.ts +0 -379
  104. package/tasks/rust.ts +0 -173
  105. package/tasks/uniffi-python.d.ts +0 -60
  106. package/tasks/uniffi-python.js +0 -178
  107. package/tasks/uniffi-release.mjs +0 -579
  108. package/tasks/uniffi.ts +0 -262
package/README.md CHANGED
@@ -45,8 +45,12 @@ instead of creating a second owner. An explicit `outdir` is the workspace root
45
45
  for naming, Git metadata, package discovery, codegen, and barrels even when the
46
46
  calling process has a different current directory.
47
47
 
48
- The unified dbx-tools release surface is enabled by default. Set
49
- `releaseMode: "disabled"` to omit its workflow and bump/version/release tasks.
48
+ The unified dbx-tools release surface is enabled by default. `bump` increments
49
+ the local `VERSION` and synchronizes generated version surfaces. `release`
50
+ commits that bump on the configured release branch, pushes it, and pushes an
51
+ annotated version tag. The generated GitHub workflow runs only for matching tag
52
+ pushes and publishes directly from that immutable commit. Set
53
+ `releaseMode: "disabled"` to omit the workflow and bump/version/release tasks.
50
54
  The inherited Projen `release` and `releaseTrigger` options are intentionally
51
55
  not part of this engine's public options because they create a competing release
52
56
  workflow.
@@ -58,13 +62,8 @@ Repository policy stays in the consuming `.projenrc.ts`:
58
62
  artifact upload, and deployment without naming a docs script or output tree.
59
63
  - `releasePythonRoot` passes the actual Python package root to local release
60
64
  preparation. Omit it when the workspace has no standard Python packages.
61
- - `releaseValidationTasks` names repository tasks that must pass in the release
62
- branch before Cargo tests, compilation, local publication, or approval.
63
- Use it for repository-specific guards that also run in release CI.
64
- - `releaseSummary` controls versioned release notes. It defaults to Cursor,
65
- Codex, Claude fallback order and writes a deterministic Git summary when every
66
- configured provider is unavailable; pass `false` to disable or provide a
67
- `providers` array to choose the order/subset.
65
+ - `releaseValidationTasks` names repository tasks that must pass in tag CI
66
+ before release artifacts are built and published.
68
67
  - `pullRequestTitlePolicy` configures semantic title types and scope policy.
69
68
  Omit it or pass `false` to disable the title job.
70
69
  - `workflowCacheIgnorePaths` excludes generated output trees that may contain
@@ -124,178 +123,70 @@ without repeating repository coordinates. Pass `repository`, `name`, or
124
123
  VS Code component; dbx-tools reuses it rather than constructing a second
125
124
  `.vscode/settings.json` owner.
126
125
 
127
- ## Add A Rust Workspace
128
-
129
- `DBXToolsRustWorkspace` discovers every source-bearing folder under its
130
- configurable `root` (default `packages/rs`), generates its Cargo manifest, and
131
- derives the crate name and repository from the parent project. A crate containing
132
- `uniffi::setup_scaffolding!()`
133
- automatically wires matching public Node and Python binding packages using the
134
- `<name>-rs` folder suffix. Node packages are named `@<scope>/<name>-rs`;
135
- Python distributions are named `<scope>-<name>-rs` and export generated values
136
- from `<scope>.<name>_rs`. Binding packages are always dedicated and
137
- never merge generated code into handwritten Node or Python packages.
138
- Repository-specific dependencies and features remain
139
- declarative options in `.projenrc.ts`; generated bindings are built separately
140
- from projen synthesis. Target-independent Node binding TypeScript is committed
141
- and remains generated/read-only, while native libraries stay ignored. Node
142
- facades compile to `lib/` and publish JavaScript entry points that plain Node
143
- can load from `node_modules`. A complete `bindings.ts` / `_bindings.ts` /
144
- `_bindings-ffi.ts` triplet is exported directly from the generated package
145
- barrel. Python keeps `bindings.py` as the generated implementation and leaves
146
- `__init__.py` as its generated package-root export. Node generation fails when
147
- direct binding names conflict.
148
- Do not create a `nodeExports` binding subpath or a handwritten type facade.
149
-
150
- Each discovered member is a native Projen `Project`, exposed as
151
- `DBXToolsRustProject`. The same class also owns standalone Cargo projects with
152
- the flat object-style options used by the Node and Python project classes:
126
+ ### Bundle Node Code For PythonMonkey
153
127
 
154
- ```ts
155
- import { project } from "@dbx-tools/projen";
128
+ Add `nodeBindings` to any `DBXToolsPythonWorkspace` package to generate a
129
+ committed CommonJS runtime and async Python wrappers from a public Node package.
130
+ The configuration is written to `pyproject.toml`, so the generation task also
131
+ works in consuming repositories after `@dbx-tools/projen` is installed.
156
132
 
157
- new project.DBXToolsRustProject({
158
- name: "my-apps-core",
159
- outdir: "native/core",
160
- version: "0.1.0",
161
- description: "Shared native runtime",
162
- repository: "https://github.com/example/my-apps",
133
+ ```ts
134
+ new project.DBXToolsPythonWorkspace(root, {
135
+ root: "packages/py",
136
+ packages: [
137
+ {
138
+ directory: "auth",
139
+ description: "Python bindings for example auth",
140
+ nodeBindings: {
141
+ package: "@example/auth",
142
+ layout: "package",
143
+ private: false,
144
+ shimRoot: "projen/shims/python-node",
145
+ functionOverrides: [
146
+ {
147
+ module: "@example/core/file-lock",
148
+ export: "acquireFileLock",
149
+ handler: "projen/shims/python-node/file-lock.ts",
150
+ },
151
+ ],
152
+ },
153
+ },
154
+ ],
163
155
  });
164
156
  ```
165
157
 
166
- The project emits concrete standalone Cargo metadata plus `compile`, `test`,
167
- `package`, `lint`, `format`, and `format:check` tasks. A nested standalone
168
- project declares its own empty Cargo workspace so a surrounding repository
169
- workspace does not absorb it accidentally. The `examples` option emits explicit
170
- Cargo example targets and `required-features`, so an optional code generator is
171
- excluded from ordinary workspace tests until its feature is enabled.
172
- `DBXToolsRustWorkspace` constructs the same class with workspace-owned metadata
173
- and keeps aggregate binding and release coordination.
174
- `DBXToolsRustWorkspaceOptions.private` supplies the default Cargo publication
175
- policy for every discovered crate; a package-level `private` value overrides it.
176
- Cargo projects use the flat object-style constructor exclusively.
177
-
178
- Rust dependencies between binding-enabled workspace crates become Node
179
- `workspace:*` and Python `internalDependencies` automatically. Python generation
180
- selects the owning crate and supplies `external_packages` imports. UBRN currently
181
- emits every linked component; the generation task discards dependency outputs
182
- and rewrites their imports to the owning package root, including its generated
183
- `uniffiModule` converter table. It never copies a dependency's records or enums.
184
- Foreign callback adapters must first be wrapped in an object created by their
185
- own native library (`createStorageHandle` for auth), because callback registries
186
- are library-local. Release wheels replace sibling Git requirements with matching
187
- native-wheel versions, and dependent publishers wait for their dependencies.
188
- Each crate builds its own `<crate>-uniffi-bindgen` executable so one target row
189
- has no colliding binary outputs. The executable requires the generated
190
- `uniffi-bindgen` feature, which enables `uniffi/cli` only in the UniFFI matrix.
191
- Packaging runs that prebuilt executable.
192
- Cargo manifests, target config, and UniFFI config are generated from structured
193
- Projen `TomlFile` objects. Local and release Python generation share one
194
- dependency-free helper for generator arguments, target-specific executable
195
- names, generated headers, generated package-root exports, and native-library
196
- placement.
197
-
198
- `sync --watch` runs a focused Rust watcher beside the OpenAPI watcher. Changes
199
- inside an existing UniFFI crate regenerate that crate and its dependent bindings
200
- in dependency order; adding or
201
- removing a crate or `setup_scaffolding!()` marker triggers a full synth. Repos
202
- without Rust crates start no Rust watcher. When Rust projects are detected,
203
- Cargo is required and the focused task fails immediately if it is unavailable.
204
- `rs:bindings` is explicit rather than part of root `pre-compile`, so ordinary
205
- JavaScript PR builds type-check committed generated bindings without performing
206
- a host Rust build. Regenerate bindings through the focused watcher or explicit
207
- task while changing a UniFFI API. Release preparation runs Cargo workspace tests
208
- without invoking UBRN.
209
-
210
- Rust release configuration is generated at `.projen/rust-release.json` from the
211
- workspace model. The release tasks consume that file directly, so consumers do
212
- not need a repository-specific helper crate or handwritten target matrix.
213
-
214
- The workspace generates one `release.yml` workflow for every ecosystem. The
215
- root `VERSION` drives every Node, Python, Cargo, native, and GitHub artifact.
216
- `bun run release` prepares one reviewed PR into `main`; it enables automatic
217
- merge by default and accepts `--no-approve` for a human-controlled merge.
218
-
219
- Release generation writes `release.yml` without scanning for or removing other
220
- workflow files. Consumers explicitly delete exact workflow files they no longer
221
- want.
222
-
223
- Release preparation uses one checkout. It commits and pushes pending source
224
- work, switches to `release/v<version>`, increments `VERSION`, synthesizes and
225
- validates the repository, and opens the release PR. After merge it detaches at
226
- the exact merge SHA, builds the complete candidate once, optionally publishes
227
- that candidate to local registries, uploads the same files to a draft GitHub
228
- Release, and restores the original branch. A failed transaction stores
229
- uncommitted release-branch state in a `release-resume:<branch>` stash. No Git
230
- worktree or second production build is involved.
231
-
232
- The draft contains `release-manifest.json`, `SHA256SUMS`, every npm archive,
233
- every Python distribution, every native binding archive, and every Rust binary.
234
- The manifest records the version, annotated tag, exact Git commit SHA, file size,
235
- and SHA-256 for each artifact. Publishing the GitHub Release is the production
236
- promotion event.
237
-
238
- `release.yml` runs on `release.published`. Its context job resolves the annotated
239
- tag, verifies main ancestry, checks out the exact commit, checks `VERSION`, and
240
- downloads and verifies the approved candidate. npm publishes the approved
241
- archives directly with the repository `NPM_TOKEN` secret. The job pins npm
242
- `11.4.2` so token authentication and GitHub provenance do not depend on the npm
243
- version bundled with the runner's Node release or opt into trusted-publisher
244
- registry authentication. PyPI
245
- publishes the approved distributions through trusted-publisher environments.
246
- Cargo publishes from the verified source checkout with `cargo publish --locked`.
247
- GitHub-hosted runners do not rebuild native release artifacts.
248
-
249
- The workflow accepts stage-specific manual recovery only for an existing
250
- published tag. npm compares archive identity and content, PyPI uses hash-aware
251
- existing-file behavior, Cargo checks existing versions, and every stage remains
252
- bound to the same tag and SHA. Manual runs default to dry-run.
253
-
254
- Set a release binary's `cli` package option and the workspace `cliRegistryPath`
255
- to generate a typed `dbx` command registry from the configured release targets.
256
- The runtime command uses `@dbx-tools/core` `bin.ensure`; the core installer
257
- contains no product registry. `releaseExcludeOs` omits a release binary from an
258
- incompatible target. UniFFI crates still produce every configured target.
259
-
260
- Set `LOCAL_CARGO_REGISTRY` to a named Cargo registry such as a loopback
261
- [Kellnr](https://kellnr.io/) instance and provide `LOCAL_CARGO_TOKEN`. Public
262
- Cargo crates also publish directly to crates.io
263
- with `CARGO_REGISTRY_TOKEN`. Override `releaseTargets` only when a consumer has
264
- additional native runners; ordinary projects inherit the maintained matrix
265
- automatically. `bun run release` also accepts repeatable `--os` and `--arch`
266
- selectors; every selected operating system is crossed with every selected
267
- architecture. Omit both filters to regenerate the complete maintained matrix.
268
- `DBX_TOOLS_RELEASE_PLATFORMS` can select the generated matrix without repeating
269
- environment parsing in a consumer.
270
-
271
- A manager can rebuild an interrupted candidate from the exact source with
272
- `bun run release:assets --version <version> --tag <tag> --sha <commit> --upload`.
273
- Candidate upload is separate from candidate construction, so retries use the
274
- already-verified files rather than rebuilding them.
275
-
276
- Public UniFFI facades are marked with `dbxToolsConfig.uniffi = true` in Node
277
- manifests and `[tool.dbx_tools.config] uniffi = true` in Python manifests. The
278
- approved npm archives are dependency-ordered and published directly with the
279
- repository `NPM_TOKEN` secret with GitHub Actions provenance. Local Verdaccio
280
- publication does not enable provenance. Python publishes the exact approved wheels and source distributions
281
- through package-specific PyPI trusted-publisher environments; binding publishers
282
- wait for their dependencies. Trusted-publisher instructions name `release.yml`
283
- and the `v*` deployment tag policy. Cargo publication checks the approved source
284
- commit and skips an already-published version during recovery.
285
- The docs jobs generate README and TypeScript API content and deploy GitHub Pages
286
- from the same workflow. When a conventional Node binding path already belongs
287
- to a root subproject, Rust mapping reuses that project and adds binding
288
- dependencies and metadata to its existing manifest.
289
-
290
- The workspace npm publisher owns compilation for normal release publication. It
291
- selects every publishable package with compiled entry points, invokes one
292
- root-level filtered compile, then packs each package exactly once with lifecycle
293
- scripts disabled. It validates the archive identity, configured access,
294
- integrity, and repository metadata before publishing those same bytes. Local
295
- release preparation passes `--skip-compile` only after its immediately preceding
296
- validation compile and verifies every expected output exists before reuse.
297
- Package `prepack` tasks remain available for standalone publishes without
298
- multiplying `tsc --build` across the monorepo release flow.
158
+ `layout: "package"` owns the complete Python package under `generated-src`.
159
+ Use the default `layout: "submodule"` to place generated bindings under
160
+ `<module>._generated` beside handwritten source. Generated wrappers convert
161
+ public function names to `snake_case`, await promises, recursively convert plain
162
+ records and arrays, and proxy returned JavaScript class instances with
163
+ `snake_case` async methods.
164
+
165
+ Set `private: true` to keep every generated symbol out of the generated
166
+ `__init__.py`. The runtime and `node_bindings.py` remain available for a
167
+ handwritten consuming package to import selectively. The default is `false`.
168
+
169
+ Every function parameter is resolved through the TypeScript compiler API and
170
+ rendered with its Python-equivalent name and type. Supported record types become
171
+ keyword-only Python dataclasses, nested records become nested dataclasses, and a
172
+ same-named exported companion's `defaults()` method supplies field defaults. A
173
+ trailing optional record can be passed as the dataclass, a dictionary, or direct
174
+ snake-case keyword fields. Generation fails with the property path when a type
175
+ cannot be represented safely in Python.
176
+
177
+ Return types use the same compiler model. Plain records become generated
178
+ `TypedDict` responses, returned clients and class instances become `Protocol`
179
+ types with typed async methods, and primitives, arrays, maps, promises, and
180
+ optional values retain their corresponding Python annotations.
181
+
182
+ The workspace creates `<name>:python-runtime`,
183
+ `<name>:python-runtime:check`, and, for workspace Node dependencies,
184
+ `<name>:python-runtime:watch`. The root sync watcher includes the watch task.
185
+ Built-in shims can make ordinary Node imports work under PythonMonkey.
186
+ `functionOverrides` replaces named exports only in the generated runtime, so the
187
+ Node package does not gain Python callbacks or alternate source files. A
188
+ replacement may use a different export name through `handlerExport`; every
189
+ other export continues to come from the original module.
299
190
 
300
191
  ## Customize Packages With Mixins
301
192
 
@@ -484,35 +375,15 @@ list, so a new package is covered without a re-synth. Work from the root:
484
375
  | `bun run barrels` | regenerate the read-only `index.ts` barrels |
485
376
  | `bun run bump` | increment `VERSION` and regenerate version surfaces |
486
377
  | `bun run version:check` | verify every generated version against `VERSION` |
487
- | `bun run release` | validate, open, and automatically merge a release PR |
488
- | `bun run release --no-approve` | open the release PR without automatic merge |
489
-
490
- `release` commits and pushes pending source work, switches to a release branch,
491
- increments `VERSION`, synthesizes manifests and registries, runs validation,
492
- writes the release summary, and opens one PR. After automatic merge it builds
493
- the candidate from the exact merge SHA, optionally publishes the same candidate
494
- to local registries, uploads it to a draft GitHub Release, and returns to the
495
- original branch. Publishing the draft starts registry deployment. Use
496
- `--no-approve` to leave the PR for manual merge, `--no-validate` to skip
497
- repository tests/compile, or `--no-local-publish` to skip local registry
498
- preflight. `VERSION` is the only base used to calculate the next version.
499
- The repository host and owner are derived from the Git remote. If the GitHub CLI
500
- has multiple accounts for that host, release preparation selects the first
501
- authenticated account with write access to the detected repository. Classic
502
- tokens must include the `workflow` scope so the release PR can update the
503
- generated workflow.
504
-
505
- The GitHub PR workflow runs the explicit `pr:validate` task through Projen's
506
- public `BuildWorkflow` `buildTask` option. That task runs synth plus the
507
- workspace TypeScript compile rather than the complete root build. Release
508
- preparation has already run Rust tests, workspace type-checking, and local
509
- package preflight before opening the PR. JavaScript behavior tests remain an
510
- explicit developer task.
511
-
512
- The generated workflow publishes the complete public workspace after the draft
513
- GitHub Release is published. Cargo, PyPI, npm, and docs share the verified tag,
514
- commit, manifest, and checksums. Documentation deployment runs only in this
515
- promotion workflow.
378
+ | `bun run release` | run the configured release transaction |
379
+
380
+ Run exactly `bun run release` from a clean `main`. It calls the existing `bump`
381
+ task, commits the generated version changes, pushes `main`, and pushes the
382
+ matching annotated `vX.Y.Z` tag. Pass `--no-bump` only to release an existing
383
+ synchronized local bump. The tag workflow verifies that the tag points at the
384
+ exact `origin/main` commit, publishes npm and PyPI directly from that checkout,
385
+ then builds and deploys documentation. Local npm and Python registry publication
386
+ remains available through the direct local publication tooling.
516
387
 
517
388
  Members intentionally keep only the tasks that something OTHER than a human
518
389
  invokes, so there is no second place to run the same thing:
@@ -541,7 +412,6 @@ from the root instead.
541
412
  ## Versioning
542
413
 
543
414
  `VERSION` is the language-neutral version seam. Real package manifests remain
544
- Projen-owned and reproduce it exactly across JavaScript, Python, Rust, UniFFI
545
- bindings, native package metadata, and runtime binary registries. Package and
415
+ Projen-owned and reproduce it exactly across JavaScript and Python packages. Package and
546
416
  artifact discovery still supplies publication order and target inventory; it
547
417
  does not create independent version ownership.
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.9.21";
6
+ export const PACKAGE_VERSION = "0.9.28";
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";
@@ -21,17 +21,17 @@ export * as project from "./src/project.ts";
21
21
  export * as projectJs from "./src/project-js.ts";
22
22
  export * as projectPredicate from "./src/project-predicate.ts";
23
23
  export * as projectPy from "./src/project-py.ts";
24
- export * as projectRs from "./src/project-rs.ts";
25
24
  export * as projenVersion from "./src/projen-version.ts";
26
25
  export * as publish from "./src/publish.ts";
26
+ export * as pythonNodeBindings from "./src/python-node-bindings.ts";
27
+ export * as pythonNodeBundle from "./src/python-node-bundle.ts";
27
28
  export * as release from "./src/release.ts";
28
29
  export * as releaseCatalog from "./src/release-catalog.ts";
29
- export * as releaseDispatch from "./src/release-dispatch.ts";
30
+ export * as releaseContext from "./src/release-context.ts";
30
31
  export * as releaseGithub from "./src/release-github.ts";
31
32
  export * as scaffold from "./src/scaffold.ts";
32
33
  export * as tags from "./src/tags.ts";
33
34
  export * as tsconfig from "./src/tsconfig.ts";
34
- export * as uniffi from "./src/uniffi.ts";
35
35
  export * as vscode from "./src/vscode.ts";
36
36
  export * as watch from "./src/watch.ts";
37
37
  export * as workspaceLock from "./src/workspace-lock.ts";
@@ -44,7 +44,7 @@ export type { DBXToolsConfigOptions } from "./src/dbx-tools-config.ts";
44
44
  export { resolvePkgRoot } from "./src/engine-root.ts";
45
45
  export type { HeaderOpts } from "./src/generated.ts";
46
46
  export type { ConstructsMixin } from "./src/mixin.ts";
47
- export type { ModuleStatement, ModuleExport } from "./src/module-exports.ts";
47
+ export type { ModuleStatement, ModuleExport, PublicFunctionExport } from "./src/module-exports.ts";
48
48
  export { repoRoot, DEFAULT_PACKAGE_ROOTS, DiscoveredPackage } from "./src/packages.ts";
49
49
  export type { RecordedPackage } from "./src/packages.ts";
50
50
  export { PnpmWorkspaceState } from "./src/pnpm-workspace.ts";
@@ -54,22 +54,20 @@ export { PackageIdentifier, DBX_TOOLS_LICENSE, DBXToolsNodeProject, ROOT_INSTALL
54
54
  export type { DBXToolsJavaScriptProject, DBXToolsReleaseMode, PullRequestTitlePolicyOptions, DBXToolsJavaScriptProjectOptions, DBXToolsTypeScriptProjectOptions } from "./src/project-js.ts";
55
55
  export { DBXToolsPythonProject, DBXToolsPythonWorkspace } from "./src/project-py.ts";
56
56
  export type { PythonRepositoryOptions, PythonPackageOptions, PythonTrustedPublisherOptions, DBXToolsPythonProjectOptions, PythonReleaseOptions, DBXToolsPythonWorkspaceOptions } from "./src/project-py.ts";
57
- export { DBXToolsRustProject, RustReleaseOs, RustReleaseCpu, UNIFFI_RELEASE_TARGETS, DBXToolsRustWorkspace } from "./src/project-rs.ts";
58
- export type { CargoDependency, CargoDependencyOptions, CargoExampleOptions, DBXToolsRustProjectOptions, RustCrateOptions, RustCliOptions, RustOpenApiOptions, DBXToolsRustWorkspaceOptions, RustReleasePlatform, UniFFIReleaseTarget, RustBindingMapping, RustOpenApiMapping, RustWorkspaceMapping, RustReleaseBinaryAssetMapping, RustReleaseBinaryMapping } from "./src/project-rs.ts";
59
57
  export { PROJEN_VERSION } from "./src/projen-version.ts";
60
58
  export { COMPILED_DIR, COMPILED_COMPILER_OPTIONS } from "./src/publish.ts";
59
+ export type { ResolvedPythonNodeFunctionOverride, ResolvedPythonNodeBindings } from "./src/python-node-bindings.ts";
60
+ export { PythonNodeBundle } from "./src/python-node-bundle.ts";
61
+ export type { PythonNodeFunctionOverride, PythonNodeBindingsOptions, PythonNodeBundleOptions } from "./src/python-node-bundle.ts";
61
62
  export { DBXToolsRelease } from "./src/release.ts";
62
- export type { ReleaseStage, ReleaseDocsOptions, ReleaseSummaryOptions, DBXToolsReleaseOptions } from "./src/release.ts";
63
+ export type { ReleaseStage, ReleaseDocsOptions, DBXToolsReleaseOptions } from "./src/release.ts";
63
64
  export { DBXToolsReleaseCatalog } from "./src/release-catalog.ts";
64
65
  export type { ReleaseProjectLanguage, ReleaseArtifactKind, ReleaseEdgeKind, ReleasePropagation, ReleaseUnitRule, DBXToolsReleaseCatalogOptions, ReleaseDependencyInput, ReleaseProjectRegistration, ExternalReleaseProjectRegistration, ReleaseArtifactRegistration, ReleaseProjectNode, ReleaseArtifact, ReleaseDependencyEdge, ReleaseUnit, ReleaseUnitGraph } from "./src/release-catalog.ts";
65
- export { RELEASE_TAG, RELEASE_SHA, RELEASE_VERSION, RELEASE_SUMMARY_DIRECTORY, RELEASE_SUMMARY_PROVIDER_NAMES, RELEASE_SUMMARY_FILE } from "./src/release-dispatch.ts";
66
- export type { ReleaseSummaryProviderName } from "./src/release-dispatch.ts";
66
+ export { RELEASE_TAG, RELEASE_SHA, RELEASE_VERSION } from "./src/release-context.ts";
67
67
  export type { GithubRepositoryIdentity, GithubAuthenticatedAccount, GithubRepositoryPermissions } from "./src/release-github.ts";
68
68
  export { AGNOSTIC_COMPILER_OPTIONS, PACKAGE_TAG_MIXINS } from "./src/tags.ts";
69
69
  export type { PackageTag } from "./src/tags.ts";
70
70
  export { DBXToolsRootTsconfig } from "./src/tsconfig.ts";
71
- export { makeDefaultedInterfaceParametersOptional, removeObsoleteInterfaceAliases, addTypeScriptExtensionsToBindingImports, addExplicitInterfaceReexports } from "./src/uniffi.ts";
72
- export type { TypeScriptBindingModule } from "./src/uniffi.ts";
73
71
  export { DBXToolsVsCode } from "./src/vscode.ts";
74
72
  export type { IgnoreGroupOptions, WatchLoopOptions } from "./src/watch.ts";
75
73
  export type { WorkspaceMutationLockOptions } from "./src/workspace-lock.ts";
package/package.json CHANGED
@@ -34,9 +34,9 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@clack/prompts": "^1.7.0",
37
- "@dbx-tools/core": "^0.9.21",
38
- "@dbx-tools/path": "^0.9.21",
39
- "@dbx-tools/shared-core": "^0.9.21",
37
+ "@dbx-tools/core": "^0.9.28",
38
+ "@dbx-tools/path": "^0.9.28",
39
+ "@dbx-tools/shared-core": "^0.9.28",
40
40
  "commander": "^15.0.0",
41
41
  "concurrently": "^10.0.3",
42
42
  "constructs": "^10.6.0",
@@ -56,7 +56,7 @@
56
56
  },
57
57
  "main": "index.ts",
58
58
  "license": "Apache-2.0",
59
- "version": "0.9.21",
59
+ "version": "0.9.28",
60
60
  "types": "index.ts",
61
61
  "type": "module",
62
62
  "exports": {
package/src/barrels.ts CHANGED
@@ -16,11 +16,6 @@
16
16
  * takes priority. This keeps the barrel auto-generated while letting you add or
17
17
  * override individual exports.
18
18
  *
19
- * A UniFFI source triplet (`bindings.ts`, `_bindings.ts`, and
20
- * `_bindings-ffi.ts`) is one special case: the internal underscore modules stay
21
- * private, while `bindings.ts` is re-exported directly instead of under a
22
- * `bindings` namespace. Generation fails when one of those direct binding names
23
- * conflicts with another top-level package export.
24
19
  *
25
20
  * Each eligible module becomes `export * as <name> from "./src/x.ts"` (camelCase
26
21
  * namespace from its path segments; invalid identifiers suffixed with `Module`),
@@ -121,9 +116,6 @@ const PACKAGE_IDENTIFIER_LINE = `export const ${PACKAGE_IDENTIFIER_EXPORT} = "";
121
116
  const PACKAGE_VERSION_LINE = `export const ${PACKAGE_VERSION_EXPORT} = "";`;
122
117
  const PACKAGE_IDENTIFIER_LINE_RE = /^export const PACKAGE_IDENTIFIER = .*;$/m;
123
118
  const PACKAGE_VERSION_LINE_RE = /^export const PACKAGE_VERSION = .*;$/m;
124
- const UNIFFI_BINDINGS_FILE = "bindings.ts";
125
- const UNIFFI_GENERATED_FILE = "_bindings.ts";
126
- const UNIFFI_FFI_FILE = "_bindings-ffi.ts";
127
119
 
128
120
  /** `config-tools` / `config_tools` -> `configTools`; `local-fs` -> `localFS`. */
129
121
  function moduleSegmentToCamel(segment: string): string {
@@ -295,61 +287,6 @@ function isLegacyBindingsExport(file: string): boolean {
295
287
  return readFileSync(file, "utf8").trim() === 'export * from "./src/bindings.ts";';
296
288
  }
297
289
 
298
- function hasUniFFIBindings(srcDir: string): boolean {
299
- return [UNIFFI_BINDINGS_FILE, UNIFFI_GENERATED_FILE, UNIFFI_FFI_FILE].every((file) =>
300
- existsSync(join(srcDir, file)),
301
- );
302
- }
303
-
304
- function bindingExportNames(srcDir: string): Set<string> {
305
- return new Set(
306
- [UNIFFI_BINDINGS_FILE, UNIFFI_GENERATED_FILE].flatMap((file) =>
307
- moduleExports(join(srcDir, file)).map((entry) => entry.name),
308
- ),
309
- );
310
- }
311
-
312
- function barrelExportNames(content: string, customPath: string): Set<string> {
313
- const names = new Set<string>([PACKAGE_IDENTIFIER_EXPORT, PACKAGE_VERSION_EXPORT]);
314
- for (const match of content.matchAll(/^export \* as (\w+) from /gm)) {
315
- names.add(match[1]!);
316
- }
317
- for (const match of content.matchAll(/^export(?: type)? \{([^}]+)\} from /gm)) {
318
- for (const specifier of match[1]!.split(",")) {
319
- const parts = specifier.trim().split(/\s+as\s+/);
320
- const name = parts.at(-1);
321
- if (name) names.add(name);
322
- }
323
- }
324
- if (existsSync(customPath) && !isLegacyBindingsExport(customPath)) {
325
- const statements = moduleStatements(customPath) as ReadonlyArray<{
326
- type: string;
327
- exported?: unknown;
328
- }>;
329
- if (
330
- statements.some(
331
- (statement) => statement.type === "ExportAllDeclaration" && !statement.exported,
332
- )
333
- ) {
334
- throw new Error(
335
- `Cannot verify UniFFI export conflicts through a bare export in ${customPath}`,
336
- );
337
- }
338
- for (const name of customExportNames(customPath)) names.add(name);
339
- }
340
- return names;
341
- }
342
-
343
- function assertNoBindingExportConflicts(srcDir: string, content: string, customPath: string): void {
344
- const other = barrelExportNames(content, customPath);
345
- const conflicts = [...bindingExportNames(srcDir)].filter((name) => other.has(name)).sort();
346
- if (conflicts.length > 0) {
347
- throw new Error(
348
- `UniFFI binding exports conflict with package exports in ${srcDir}: ${conflicts.join(", ")}`,
349
- );
350
- }
351
- }
352
-
353
290
  /** Read the authoritative npm package name and version emitted by the package project. */
354
291
  function packageMetadata(pkgDir: string): { identifier: string; version: string } {
355
292
  const manifestPath = join(pkgDir, "package.json");
@@ -441,10 +378,7 @@ function generateForPackage(pkgDir: string): number {
441
378
  if (!existing || (!isSourceExt(existing) && isSourceExt(f))) byModulePath.set(stem, f);
442
379
  }
443
380
  const modulePaths = [...byModulePath.keys()].sort((a, b) => a.localeCompare(b));
444
- const uniffiBindings = hasUniFFIBindings(srcDir);
445
- const namespacedModulePaths = uniffiBindings
446
- ? modulePaths.filter((modulePath) => modulePath !== "bindings")
447
- : modulePaths;
381
+ const namespacedModulePaths = modulePaths;
448
382
 
449
383
  // No eligible modules -> no barrel: drop any stale root barrel and bail.
450
384
  if (modulePaths.length === 0) {
@@ -479,13 +413,6 @@ function generateForPackage(pkgDir: string): number {
479
413
  content = hoistUniqueExports(content, pkgDir, suppress);
480
414
  // A sibling `exports.ts` overrides/extends the generated barrel and wins on conflict.
481
415
  content = mergeCustomExports(content, pkgDir);
482
- if (uniffiBindings) {
483
- assertNoBindingExportConflicts(srcDir, content, customPath);
484
- content = content.replace(
485
- PACKAGE_VERSION_LINE,
486
- `${PACKAGE_VERSION_LINE}\nexport * from "./src/bindings.ts";`,
487
- );
488
- }
489
416
 
490
417
  // Package metadata is blanked for the structural comparison, then restored
491
418
  // from package.json so a version-only change still rewrites the barrel.