@dbx-tools/projen 0.6.62 → 0.6.64

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/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.62",
30
- "@dbx-tools/path": "0.6.62",
31
- "@dbx-tools/shared-core": "0.6.62",
29
+ "@dbx-tools/core": "0.6.64",
30
+ "@dbx-tools/path": "0.6.64",
31
+ "@dbx-tools/shared-core": "0.6.64",
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.62",
50
+ "version": "0.6.64",
51
51
  "types": "index.ts",
52
52
  "type": "module",
53
53
  "exports": {
package/src/bun-app.ts CHANGED
@@ -141,6 +141,7 @@ import tailwind from "bun-plugin-tailwind";
141
141
  let options: Bun.BuildConfig = {
142
142
  entrypoints: ["./index.html"],
143
143
  outdir: "./dist",
144
+ define: { "process.env.NODE_ENV": JSON.stringify("production") },
144
145
  minify: true,
145
146
  splitting: true,
146
147
  publicPath: "/",
package/tasks/bump.ts CHANGED
@@ -294,9 +294,11 @@ program
294
294
  // keep `0.0.0` on disk, projen-owned, so it unlocks each briefly), then
295
295
  // `bun publish`es each non-private one - and bun natively strips the
296
296
  // `workspace:`/`catalog:` protocols in the packed tarball, resolving each
297
- // to the version just set. The next `projen` synth restores the manifests
298
- // to `0.0.0`; the release version lives in the git tag. Provenance is off
299
- // for a local registry (no OIDC), so `NPM_CONFIG_PROVENANCE` is unset.
297
+ // to the version just set. `publish.ts` restores every manifest it touched
298
+ // at exit, so this leaves the worktree matching the release commit that was
299
+ // just pushed - the release version lives in the git tag, not on disk.
300
+ // Provenance is off for a local registry (no OIDC), so
301
+ // `NPM_CONFIG_PROVENANCE` is unset.
300
302
  // `publish.ts` is this task's SIBLING in the engine's `tasks/` dir; resolve
301
303
  // it off `import.meta.url` (works whether the engine is source-linked in-repo
302
304
  // or installed under node_modules) rather than a repo-relative `tasks/...`
package/tasks/publish.ts CHANGED
@@ -37,9 +37,15 @@
37
37
  * repo-relative) skips a member that releases on its OWN tag namespace (e.g.
38
38
  * `projen`, published by `projen-release`, not the main `release`).
39
39
  *
40
+ * `--no-restore` keeps the edits on disk instead of undoing them at exit. Only
41
+ * needed when a LATER process must still see them - `--stamp-only` implies it,
42
+ * since its whole job is to stamp the workspace for a `bun publish` that runs
43
+ * afterwards from another directory.
44
+ *
40
45
  * The disk manifests normally carry `version: 0.0.0` (projen owns them, read-only);
41
- * this unlocks each only long enough to set the version + publish. The next
42
- * `projen` synth restores them - the release version lives in the git tag.
46
+ * this unlocks each only long enough to set the version + publish, then RESTORES
47
+ * every one it touched byte-for-byte (and re-locks the mode) on the way out - see
48
+ * {@link restoreManifests}. The release version lives in the git tag, not on disk.
43
49
  */
44
50
  import { chmodSync, existsSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
45
51
  import { dirname, join, resolve } from "node:path";
@@ -49,6 +55,29 @@ import { parse } from "yaml";
49
55
 
50
56
  const logger = log.logger("dbx-tools:publish");
51
57
 
58
+ /** A manifest's on-disk bytes + mode, captured before this task edits it. */
59
+ interface ManifestBackup {
60
+ readonly content: string;
61
+ readonly mode: number;
62
+ }
63
+
64
+ /**
65
+ * Original state of every manifest this task has unlocked, keyed by path.
66
+ *
67
+ * Publishing has to mutate manifests projen owns (the version stamp, so a
68
+ * `workspace:*` sibling resolves to the release version, and the `publishConfig`
69
+ * entry-point substitution bun won't do itself). Those edits are only ever meant
70
+ * to reach the packed TARBALL, so every one is undone by {@link restoreManifests}
71
+ * before the process ends.
72
+ *
73
+ * Leaving them on disk is what used to strand a local `bun run bump` with ~34
74
+ * modified `package.json` files - version stamps and `lib/` entry points - after
75
+ * the release commit was already made, so the tree diverged from the commit that
76
+ * was just pushed and every subsequent `git status` needed a manual revert. CI
77
+ * never noticed because a fresh checkout is discarded.
78
+ */
79
+ const manifestBackups = new Map<string, ManifestBackup>();
80
+
52
81
  /**
53
82
  * Workspace member dirs (absolute), read from the root `pnpm-workspace.yaml` - the
54
83
  * file the engine keeps for the Databricks Apps pnpm deploy, which also lists every
@@ -74,9 +103,43 @@ function run(cwd: string, command: string, args: string[], path: string): void {
74
103
  });
75
104
  }
76
105
 
77
- /** Make a projen-readonly manifest writable so `bun pm pkg set` / `bun publish` can edit it. */
106
+ /**
107
+ * Make a projen-readonly manifest writable so `bun pm pkg set` / `bun publish` can
108
+ * edit it, recording its original bytes + mode for {@link restoreManifests} the
109
+ * first time it is seen. Idempotent, so a manifest unlocked twice (version stamp,
110
+ * then `publishConfig`) keeps its PRE-EDIT backup rather than overwriting it with
111
+ * the already-stamped content.
112
+ */
78
113
  function unlockManifest(pkgPath: string): void {
79
- chmodSync(pkgPath, statSync(pkgPath).mode | 0o200);
114
+ const mode = statSync(pkgPath).mode;
115
+ if (!manifestBackups.has(pkgPath)) {
116
+ manifestBackups.set(pkgPath, { content: readFileSync(pkgPath, "utf8"), mode });
117
+ }
118
+ chmodSync(pkgPath, mode | 0o200);
119
+ }
120
+
121
+ /**
122
+ * Put every manifest this task edited back exactly as it was found, mode included.
123
+ *
124
+ * Runs from an `exit` handler so a clean finish and a failure partway through the
125
+ * publish loop are covered alike - a `bun publish` that dies on package 12 of 34
126
+ * must not leave the first 11 stamped. Best-effort per file: one unwritable
127
+ * manifest is logged and the rest are still restored, since a partial restore
128
+ * beats none.
129
+ *
130
+ * Not registered under `--stamp-only`, where the stamps ARE the deliverable.
131
+ */
132
+ function restoreManifests(): void {
133
+ for (const [pkgPath, backup] of manifestBackups) {
134
+ try {
135
+ chmodSync(pkgPath, backup.mode | 0o200);
136
+ writeFileSync(pkgPath, backup.content);
137
+ chmodSync(pkgPath, backup.mode);
138
+ } catch (cause) {
139
+ logger.warn(`could not restore ${pkgPath}`, { cause });
140
+ }
141
+ }
142
+ manifestBackups.clear();
80
143
  }
81
144
 
82
145
  /** Entry-point fields projen writes as `.ts` source in-repo and rewrites to `lib/` for publish. */
@@ -87,8 +150,9 @@ const PUBLISH_CONFIG_ENTRY_FIELDS = ["main", "types", "bin", "exports"] as const
87
150
  * the way pnpm/npm do at pack time but `bun publish` does NOT (see the module
88
151
  * doc). Idempotent, writes only when something changes, and leaves `publishConfig`
89
152
  * in place (npm ignores it once the top-level fields already point at `lib/`). The
90
- * manifest must already be unlocked. The next `projen` synth restores the `.ts`
91
- * entry points, so this only affects the packed tarball - like the version stamp.
153
+ * manifest must already be unlocked. {@link restoreManifests} puts the `.ts` entry
154
+ * points back at exit, so this only ever affects the packed tarball - like the
155
+ * version stamp.
92
156
  */
93
157
  function applyPublishConfig(pkgPath: string): void {
94
158
  const pkg = JSON.parse(readFileSync(pkgPath, "utf8")) as Record<string, unknown>;
@@ -133,12 +197,19 @@ const dryRun = rest.includes("--dry-run");
133
197
  // own `bun publish` (run separately, in `projen/`) resolves `workspace:*` siblings
134
198
  // to the release version; publishing every member here would double-publish them.
135
199
  const stampOnly = rest.includes("--stamp-only");
200
+ // Undo the manifest edits at exit unless a later process still needs them. Implied
201
+ // off by `--stamp-only`, whose stamps exist precisely for a subsequent `bun publish`.
202
+ const restore = !stampOnly && !rest.includes("--no-restore");
136
203
  const excluded = new Set(
137
204
  rest.reduce<string[]>((acc, arg, i) => (arg === "--exclude" ? [...acc, rest[i + 1]] : acc), []),
138
205
  );
139
206
 
140
207
  const root = process.cwd();
141
208
  const path = enrichedPath(root);
209
+ // Registered BEFORE the first manifest edit so no exit path can skip it: a clean
210
+ // finish and a `bun publish` failure mid-loop both land here, so a publish that
211
+ // dies partway does not leave half the workspace stamped.
212
+ if (restore) process.on("exit", restoreManifests);
142
213
  const members = workspaceMembers(root)
143
214
  .filter((dir) => existsSync(join(dir, "package.json")))
144
215
  .filter((dir) => !excluded.has(resolve(root, dir).replace(`${resolve(root)}/`, "")));