@smoothbricks/cli 0.10.4 → 0.10.5

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/dist/cli.js CHANGED
@@ -50,7 +50,7 @@ function buildProgram() {
50
50
  });
51
51
  monorepo.command('update').action(async () => {
52
52
  const { updateManagedFiles } = await import('./monorepo/index.js');
53
- updateManagedFiles(await findRepoRoot());
53
+ await updateManagedFiles(await findRepoRoot());
54
54
  });
55
55
  monorepo
56
56
  .command('check')
@@ -73,10 +73,10 @@ function buildProgram() {
73
73
  monorepo
74
74
  .command('sync-bun-lockfile-versions')
75
75
  .option('--stage', 'stage bun.lock when versions were resynced; quiet when clean')
76
- .option('--mode <mode>', 'install: match package.json (CI); publish: map unpublished -next to last stable tag (pre-pack)', 'publish')
76
+ .option('--mode <mode>', 'install: match package.json (default, CI); publish: map unpublished -next to last stable tag (pre-pack only)', 'install')
77
77
  .action(async (options) => {
78
78
  const { syncBunLockfileVersions } = await import('./monorepo/index.js');
79
- const mode = options.mode === 'install' ? 'install' : 'publish';
79
+ const mode = options.mode === 'publish' ? 'publish' : 'install';
80
80
  syncBunLockfileVersions(await findRepoRoot(), {
81
81
  mode,
82
82
  ...(options.stage ? { log: false, stage: true } : {}),
@@ -42,6 +42,8 @@ export interface PackageJson {
42
42
  devDependencies?: StringMap;
43
43
  peerDependencies?: StringMap;
44
44
  optionalDependencies?: StringMap;
45
+ /** Bun patchedDependencies map (package@version → patch path). */
46
+ patchedDependencies?: StringMap;
45
47
  engines?: StringMap;
46
48
  scripts?: StringMap;
47
49
  publishConfig?: PackagePublishConfig;
@@ -98,7 +100,7 @@ export declare function isPackageJson(value: unknown): value is PackageJson;
98
100
  /** Ensure package.json.scripts exists. */
99
101
  export declare function ensureScripts(pkg: PackageJson): StringMap;
100
102
  /** Ensure package.json.dependencies (or other string-map dep field) exists. */
101
- export declare function ensureDependencyMap(pkg: PackageJson, key: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies'): StringMap;
103
+ export declare function ensureDependencyMap(pkg: PackageJson, key: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies' | 'patchedDependencies'): StringMap;
102
104
  /** Ensure package.json.engines exists. */
103
105
  export declare function ensureEngines(pkg: PackageJson): StringMap;
104
106
  /** Ensure package.json.nx exists. */
@@ -1 +1 @@
1
- {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/lib/json.ts"],"names":[],"mappings":"AAGA,sDAAsD;AACtD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,uBAAuB,CAAC;IAChD,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,oBAAoB,CAAC,EAAE,SAAS,CAAC;IACjC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACxC,EAAE,CAAC,EAAE,eAAe,CAAC;IACrB,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,mEAAmE;AACnE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,gBAAgB,GAAG,IAAI,GAAG,SAAS,CAAC;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,iBAAiB,CAAC;AAErD,yDAAyD;AACzD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,MAAM;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;CAChF;AAED,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,uCAA0C,CAAC;AAE5E,4FAA4F;AAC5F,eAAO,MAAM,sBAAsB,yCAA4C,CAAC;AAEhF,yEAAyE;AACzE,eAAO,MAAM,eAAe,kCAAqC,CAAC;AAElE,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,oCAAuC,CAAC;AAIzE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAS/D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAM5D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK9C;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED,0CAA0C;AAC1C,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS,CAOzD;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,cAAc,GAAG,iBAAiB,GAAG,kBAAkB,GAAG,sBAAsB,GACpF,SAAS,CAQX;AAED,0CAA0C;AAC1C,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS,CAOzD;AAED,qCAAqC;AACrC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,eAAe,CAO1D;AAED,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,EAAE,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAOnF;AAED,gDAAgD;AAChD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,WAAW,GAAG,oBAAoB,CAO1E;AAED,sEAAsE;AACtE,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG,iBAAiB,CAO1E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAMxF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAM/F;AAED,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,gBAAgB,EAChE,KAAK,EAAE,MAAM,GACZ,OAAO,CAMT;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,gBAAgB,EAChE,KAAK,EAAE,MAAM,GACZ,OAAO,CAMT;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAMrE;AAED,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAM5F;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,iBAAiB,EAC7B,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,WAAW,EACjC,KAAK,EAAE,MAAM,GACZ,OAAO,CAMT;AAED,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,iBAAiB,EAC7B,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,WAAW,EACjC,KAAK,EAAE,MAAM,GACZ,OAAO,CAMT"}
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/lib/json.ts"],"names":[],"mappings":"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"}
package/dist/lib/json.js CHANGED
@@ -16,13 +16,14 @@ export const parsePackageJsonText = (() => {
16
16
  const _ip11 = (input, _vctx = {}) => undefined === input["devDependencies"] || "object" === typeof input["devDependencies"] && null !== input["devDependencies"] && false === Array.isArray(input["devDependencies"]) && _io1(input["devDependencies"], _vctx);
17
17
  const _ip12 = (input, _vctx = {}) => undefined === input["peerDependencies"] || "object" === typeof input["peerDependencies"] && null !== input["peerDependencies"] && false === Array.isArray(input["peerDependencies"]) && _io1(input["peerDependencies"], _vctx);
18
18
  const _ip13 = (input, _vctx = {}) => undefined === input["optionalDependencies"] || "object" === typeof input["optionalDependencies"] && null !== input["optionalDependencies"] && false === Array.isArray(input["optionalDependencies"]) && _io1(input["optionalDependencies"], _vctx);
19
- const _ip14 = (input, _vctx = {}) => undefined === input["engines"] || "object" === typeof input["engines"] && null !== input["engines"] && false === Array.isArray(input["engines"]) && _io1(input["engines"], _vctx);
20
- const _ip15 = (input, _vctx = {}) => undefined === input["scripts"] || "object" === typeof input["scripts"] && null !== input["scripts"] && false === Array.isArray(input["scripts"]) && _io1(input["scripts"], _vctx);
21
- const _ip16 = (input, _vctx = {}) => undefined === input["publishConfig"] || "object" === typeof input["publishConfig"] && null !== input["publishConfig"] && false === Array.isArray(input["publishConfig"]) && _io4(input["publishConfig"], _vctx);
22
- const _ip17 = (input, _vctx = {}) => null !== input["repository"] && (undefined === input["repository"] || "string" === typeof input["repository"] || "object" === typeof input["repository"] && null !== input["repository"] && false === Array.isArray(input["repository"]) && _io5(input["repository"], _vctx));
23
- const _ip18 = (input, _vctx = {}) => undefined === input["nx"] || "object" === typeof input["nx"] && null !== input["nx"] && false === Array.isArray(input["nx"]) && _io6(input["nx"], _vctx);
24
- const _ip19 = (input, _vctx = {}) => undefined === input["smoo"] || "object" === typeof input["smoo"] && null !== input["smoo"] && false === Array.isArray(input["smoo"]) && _io12(input["smoo"], _vctx);
25
- const _io0 = (input, _vctx = {}) => _ip0(input, _vctx) && _ip1(input, _vctx) && _ip2(input, _vctx) && _ip3(input, _vctx) && _ip4(input, _vctx) && _ip5(input, _vctx) && _ip6(input, _vctx) && _ip7(input, _vctx) && _ip8(input, _vctx) && _ip9(input, _vctx) && _ip10(input, _vctx) && _ip11(input, _vctx) && _ip12(input, _vctx) && _ip13(input, _vctx) && _ip14(input, _vctx) && _ip15(input, _vctx) && _ip16(input, _vctx) && _ip17(input, _vctx) && _ip18(input, _vctx) && _ip19(input, _vctx);
19
+ const _ip14 = (input, _vctx = {}) => undefined === input["patchedDependencies"] || "object" === typeof input["patchedDependencies"] && null !== input["patchedDependencies"] && false === Array.isArray(input["patchedDependencies"]) && _io1(input["patchedDependencies"], _vctx);
20
+ const _ip15 = (input, _vctx = {}) => undefined === input["engines"] || "object" === typeof input["engines"] && null !== input["engines"] && false === Array.isArray(input["engines"]) && _io1(input["engines"], _vctx);
21
+ const _ip16 = (input, _vctx = {}) => undefined === input["scripts"] || "object" === typeof input["scripts"] && null !== input["scripts"] && false === Array.isArray(input["scripts"]) && _io1(input["scripts"], _vctx);
22
+ const _ip17 = (input, _vctx = {}) => undefined === input["publishConfig"] || "object" === typeof input["publishConfig"] && null !== input["publishConfig"] && false === Array.isArray(input["publishConfig"]) && _io4(input["publishConfig"], _vctx);
23
+ const _ip18 = (input, _vctx = {}) => null !== input["repository"] && (undefined === input["repository"] || "string" === typeof input["repository"] || "object" === typeof input["repository"] && null !== input["repository"] && false === Array.isArray(input["repository"]) && _io5(input["repository"], _vctx));
24
+ const _ip19 = (input, _vctx = {}) => undefined === input["nx"] || "object" === typeof input["nx"] && null !== input["nx"] && false === Array.isArray(input["nx"]) && _io6(input["nx"], _vctx);
25
+ const _ip20 = (input, _vctx = {}) => undefined === input["smoo"] || "object" === typeof input["smoo"] && null !== input["smoo"] && false === Array.isArray(input["smoo"]) && _io12(input["smoo"], _vctx);
26
+ const _io0 = (input, _vctx = {}) => _ip0(input, _vctx) && _ip1(input, _vctx) && _ip2(input, _vctx) && _ip3(input, _vctx) && _ip4(input, _vctx) && _ip5(input, _vctx) && _ip6(input, _vctx) && _ip7(input, _vctx) && _ip8(input, _vctx) && _ip9(input, _vctx) && _ip10(input, _vctx) && _ip11(input, _vctx) && _ip12(input, _vctx) && _ip13(input, _vctx) && _ip14(input, _vctx) && _ip15(input, _vctx) && _ip16(input, _vctx) && _ip17(input, _vctx) && _ip18(input, _vctx) && _ip19(input, _vctx) && _ip20(input, _vctx);
26
27
  const _io1 = (input, _vctx = {}) => Object.keys(input).every(key => {
27
28
  const value = input[key];
28
29
  if (undefined === value)
@@ -128,13 +129,14 @@ const isPackageJsonValue = (() => {
128
129
  const _ip11 = (input, _vctx = {}) => undefined === input["devDependencies"] || "object" === typeof input["devDependencies"] && null !== input["devDependencies"] && false === Array.isArray(input["devDependencies"]) && _io1(input["devDependencies"], _vctx);
129
130
  const _ip12 = (input, _vctx = {}) => undefined === input["peerDependencies"] || "object" === typeof input["peerDependencies"] && null !== input["peerDependencies"] && false === Array.isArray(input["peerDependencies"]) && _io1(input["peerDependencies"], _vctx);
130
131
  const _ip13 = (input, _vctx = {}) => undefined === input["optionalDependencies"] || "object" === typeof input["optionalDependencies"] && null !== input["optionalDependencies"] && false === Array.isArray(input["optionalDependencies"]) && _io1(input["optionalDependencies"], _vctx);
131
- const _ip14 = (input, _vctx = {}) => undefined === input["engines"] || "object" === typeof input["engines"] && null !== input["engines"] && false === Array.isArray(input["engines"]) && _io1(input["engines"], _vctx);
132
- const _ip15 = (input, _vctx = {}) => undefined === input["scripts"] || "object" === typeof input["scripts"] && null !== input["scripts"] && false === Array.isArray(input["scripts"]) && _io1(input["scripts"], _vctx);
133
- const _ip16 = (input, _vctx = {}) => undefined === input["publishConfig"] || "object" === typeof input["publishConfig"] && null !== input["publishConfig"] && false === Array.isArray(input["publishConfig"]) && _io4(input["publishConfig"], _vctx);
134
- const _ip17 = (input, _vctx = {}) => null !== input["repository"] && (undefined === input["repository"] || "string" === typeof input["repository"] || "object" === typeof input["repository"] && null !== input["repository"] && false === Array.isArray(input["repository"]) && _io5(input["repository"], _vctx));
135
- const _ip18 = (input, _vctx = {}) => undefined === input["nx"] || "object" === typeof input["nx"] && null !== input["nx"] && false === Array.isArray(input["nx"]) && _io6(input["nx"], _vctx);
136
- const _ip19 = (input, _vctx = {}) => undefined === input["smoo"] || "object" === typeof input["smoo"] && null !== input["smoo"] && false === Array.isArray(input["smoo"]) && _io12(input["smoo"], _vctx);
137
- const _io0 = (input, _vctx = {}) => _ip0(input, _vctx) && _ip1(input, _vctx) && _ip2(input, _vctx) && _ip3(input, _vctx) && _ip4(input, _vctx) && _ip5(input, _vctx) && _ip6(input, _vctx) && _ip7(input, _vctx) && _ip8(input, _vctx) && _ip9(input, _vctx) && _ip10(input, _vctx) && _ip11(input, _vctx) && _ip12(input, _vctx) && _ip13(input, _vctx) && _ip14(input, _vctx) && _ip15(input, _vctx) && _ip16(input, _vctx) && _ip17(input, _vctx) && _ip18(input, _vctx) && _ip19(input, _vctx);
132
+ const _ip14 = (input, _vctx = {}) => undefined === input["patchedDependencies"] || "object" === typeof input["patchedDependencies"] && null !== input["patchedDependencies"] && false === Array.isArray(input["patchedDependencies"]) && _io1(input["patchedDependencies"], _vctx);
133
+ const _ip15 = (input, _vctx = {}) => undefined === input["engines"] || "object" === typeof input["engines"] && null !== input["engines"] && false === Array.isArray(input["engines"]) && _io1(input["engines"], _vctx);
134
+ const _ip16 = (input, _vctx = {}) => undefined === input["scripts"] || "object" === typeof input["scripts"] && null !== input["scripts"] && false === Array.isArray(input["scripts"]) && _io1(input["scripts"], _vctx);
135
+ const _ip17 = (input, _vctx = {}) => undefined === input["publishConfig"] || "object" === typeof input["publishConfig"] && null !== input["publishConfig"] && false === Array.isArray(input["publishConfig"]) && _io4(input["publishConfig"], _vctx);
136
+ const _ip18 = (input, _vctx = {}) => null !== input["repository"] && (undefined === input["repository"] || "string" === typeof input["repository"] || "object" === typeof input["repository"] && null !== input["repository"] && false === Array.isArray(input["repository"]) && _io5(input["repository"], _vctx));
137
+ const _ip19 = (input, _vctx = {}) => undefined === input["nx"] || "object" === typeof input["nx"] && null !== input["nx"] && false === Array.isArray(input["nx"]) && _io6(input["nx"], _vctx);
138
+ const _ip20 = (input, _vctx = {}) => undefined === input["smoo"] || "object" === typeof input["smoo"] && null !== input["smoo"] && false === Array.isArray(input["smoo"]) && _io12(input["smoo"], _vctx);
139
+ const _io0 = (input, _vctx = {}) => _ip0(input, _vctx) && _ip1(input, _vctx) && _ip2(input, _vctx) && _ip3(input, _vctx) && _ip4(input, _vctx) && _ip5(input, _vctx) && _ip6(input, _vctx) && _ip7(input, _vctx) && _ip8(input, _vctx) && _ip9(input, _vctx) && _ip10(input, _vctx) && _ip11(input, _vctx) && _ip12(input, _vctx) && _ip13(input, _vctx) && _ip14(input, _vctx) && _ip15(input, _vctx) && _ip16(input, _vctx) && _ip17(input, _vctx) && _ip18(input, _vctx) && _ip19(input, _vctx) && _ip20(input, _vctx);
138
140
  const _io1 = (input, _vctx = {}) => Object.keys(input).every(key => {
139
141
  const value = input[key];
140
142
  if (undefined === value)
@@ -30,7 +30,7 @@ export interface SetupTestTracingShell {
30
30
  }
31
31
  export declare function initMonorepo(root: string, options: InitOptions): Promise<void>;
32
32
  export declare function validateMonorepo(root: string, options?: ValidateOptions): Promise<void>;
33
- export declare function updateManagedFiles(root: string): void;
33
+ export declare function updateManagedFiles(root: string): Promise<void>;
34
34
  export declare function checkManagedFiles(root: string, options?: {
35
35
  warn?: boolean;
36
36
  }): void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/monorepo/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAMxD,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpF;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBjG;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAErD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,IAAI,CAUtF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,GAAE,4BAAiC,EAC1C,IAAI,SAAgB,GACnB,IAAI,CAgBN;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAW3G;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI5D;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,uBAAuB,EAChC,KAAK,GAAE,qBAAoD,GAC1D,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAED,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/monorepo/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAOxD,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpF;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBjG;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAapE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,IAAI,CAUtF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,GAAE,4BAAiC,EAC1C,IAAI,SAAgB,GACnB,IAAI,CAgBN;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAW3G;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI5D;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,uBAAuB,EAChC,KAAK,GAAE,qBAAoD,GAC1D,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAED,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,CAAC"}
@@ -9,6 +9,7 @@ import { applyManagedFiles, printResults, warnOnManagedFileDrift } from './manag
9
9
  import { listValidCommitScopes, validatePublicTags } from './package-policy.js';
10
10
  import { runInitPacks, runValidatePacks } from './packs/index.js';
11
11
  import { syncRootRuntimeVersions } from './runtime.js';
12
+ import { applyToolConfigDefaults } from './tool-validation.js';
12
13
  export async function initMonorepo(root, options) {
13
14
  if (options.runtimeOnly) {
14
15
  await syncRootRuntimeVersions(root);
@@ -35,8 +36,19 @@ export async function validateMonorepo(root, options = {}) {
35
36
  console.log('🟢 Monorepo configuration is valid.');
36
37
  }
37
38
  }
38
- export function updateManagedFiles(root) {
39
+ export async function updateManagedFiles(root) {
39
40
  printResults(applyManagedFiles(root, 'update'));
41
+ // Tool dependency policy (typescript API 6, @typescript/native for ttsc, nx, …)
42
+ // lives next to managed templates — update must install them, not only rewrite files.
43
+ await applyToolConfigDefaults(root);
44
+ syncBunLockfileVersions(root, { mode: 'install' });
45
+ console.log('installing workspace dependencies (bun install)');
46
+ const install = await $ `bun install --no-summary`.cwd(root).nothrow();
47
+ if (install.exitCode !== 0) {
48
+ const stderr = decode(install.stderr).trim();
49
+ const stdout = decode(install.stdout).trim();
50
+ throw new Error(`bun install failed after monorepo update${stderr || stdout ? `:\n${stderr || stdout}` : ''}`);
51
+ }
40
52
  }
41
53
  export function checkManagedFiles(root, options = {}) {
42
54
  if (options.warn === true) {
@@ -3,9 +3,10 @@ export interface SyncBunLockfileVersionsOptions {
3
3
  /** `git add` bun.lock when versions were resynced. */
4
4
  stage?: boolean;
5
5
  /**
6
- * `install` (default for validation): lockfile must match package.json.
6
+ * `install` (default): lockfile must match package.json (including -next).
7
7
  * `publish`: rewrite unpublished prerelease package.json versions to the last
8
8
  * stable git tag so `bun pm pack` embeds installable dependency versions.
9
+ * Only use publish mode around pack; never leave the tree in publish mode.
9
10
  */
10
11
  mode?: 'install' | 'publish';
11
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../../src/monorepo/lockfile.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,8BAA8B;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAC9B;AAmBD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,8BAAmC,GAAG,MAAM,CAqD1G;AAED,4EAA4E;AAC5E,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA8BhE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAE9G"}
1
+ {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../../src/monorepo/lockfile.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,8BAA8B;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CAC9B;AAmBD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,8BAAmC,GAAG,MAAM,CAqD1G;AAED,4EAA4E;AAC5E,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA8BhE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAE9G"}
@@ -21,7 +21,7 @@ import { escapeRegex, getWorkspacePackages } from '../lib/workspace.js';
21
21
  // rewrites lockfile back to package.json and frozen CI then fails.
22
22
  export function syncBunLockfileVersions(root, options = {}) {
23
23
  const log = options.log ?? true;
24
- const mode = options.mode ?? 'publish';
24
+ const mode = options.mode ?? 'install';
25
25
  const lockfilePath = join(root, 'bun.lock');
26
26
  if (!existsSync(lockfilePath)) {
27
27
  throw new Error('bun.lock not found');
@@ -1 +1 @@
1
- {"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,yEAAyE,CAAC;AAU3G,sFAAsF;AACtF,iBAAS,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAIlF;AAED,uCAAuC;AACvC,eAAO,MAAM,wBAAwB,0BAAoB,CAAC;AAE1D;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAEnD,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;8BAE8B;AAC9B,iBAAS,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAkCxG;AAED,wCAAwC;AACxC,eAAO,MAAM,+BAA+B,iCAA2B,CAAC;AAExE;+EAC+E;AAC/E,iBAAS,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAqBtF;AAED,yCAAyC;AACzC,eAAO,MAAM,gCAAgC,kCAA4B,CAAC;AAE1E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;CACxG;AAyHD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,EAAE,CAG/F;AA6FD,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAMlF;AAgGD,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAIxD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkBzD"}
1
+ {"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,yEAAyE,CAAC;AAU3G,sFAAsF;AACtF,iBAAS,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAIlF;AAED,uCAAuC;AACvC,eAAO,MAAM,wBAAwB,0BAAoB,CAAC;AAE1D;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAEnD,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;8BAE8B;AAC9B,iBAAS,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAkCxG;AAED,wCAAwC;AACxC,eAAO,MAAM,+BAA+B,iCAA2B,CAAC;AAExE;+EAC+E;AAC/E,iBAAS,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAqBtF;AAED,yCAAyC;AACzC,eAAO,MAAM,gCAAgC,kCAA4B,CAAC;AAE1E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;CACxG;AA8HD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,EAAE,CAG/F;AA6FD,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAMlF;AAgGD,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAIxD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkBzD"}
@@ -146,6 +146,11 @@ const managedFiles = [
146
146
  target: 'tooling/direnv/merge-newer-pins.sh',
147
147
  executable: true,
148
148
  },
149
+ {
150
+ kind: 'raw',
151
+ source: 'patches/ttsc@0.19.3.patch',
152
+ target: 'patches/ttsc@0.19.3.patch',
153
+ },
149
154
  {
150
155
  kind: 'generated',
151
156
  source: 'ci-workflow',
@@ -43,7 +43,7 @@ const packs = [
43
43
  warnOnManagedFileDrift(ctx.root);
44
44
  return (runtimeFailures +
45
45
  validateRootPackagePolicy(ctx.root) +
46
- validateToolConfig(ctx.root) +
46
+ (await validateToolConfig(ctx.root)) +
47
47
  validateNxProjectNames(ctx.root) +
48
48
  validateNxReleaseConfig(ctx.root) +
49
49
  validateBunLockfileVersions(ctx.root) +
@@ -9,7 +9,7 @@ export interface ToolContext {
9
9
  policy: ToolPolicy;
10
10
  }
11
11
  export declare function applyToolConfigDefaults(root: string): Promise<void>;
12
- export declare function validateToolConfig(root: string): number;
12
+ export declare function validateToolConfig(root: string): Promise<number>;
13
13
  export declare function applyRootDevDependencyDefaults(root: string, context: ToolContext): Promise<void>;
14
14
  export declare function applyToolingPackageDefaults(root: string, policy: ToolPolicy): void;
15
15
  export declare function applyToolingWorkspaceDefault(root: string): void;
@@ -18,5 +18,5 @@ export declare function validateRootDevDependencies(policy: ToolPolicy, rootPack
18
18
  export declare function validateToolingPackage(root: string, policy: ToolPolicy): number;
19
19
  export declare function validateToolingWorkspace(rootPackage: PackageJson | null): number;
20
20
  export declare function validateDevenvPackages(root: string): number;
21
- export declare function readToolContext(root: string): ToolContext;
21
+ export declare function readToolContext(root: string): Promise<ToolContext>;
22
22
  //# sourceMappingURL=tool-validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-validation.d.ts","sourceRoot":"","sources":["../../src/monorepo/tool-validation.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AAU9E,MAAM,WAAW,UAAU;IACzB,sBAAsB,EAAE,OAAO,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,UAAU,CAAC;CACpB;AA0CD,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKzE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBtG;AAoCD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBlF;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAY/D;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA0B7D;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAyBvG;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAoB/E;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAWhF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB3D;AA0DD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAQzD"}
1
+ {"version":3,"file":"tool-validation.d.ts","sourceRoot":"","sources":["../../src/monorepo/tool-validation.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AAU9E,MAAM,WAAW,UAAU;IACzB,sBAAsB,EAAE,OAAO,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,UAAU,CAAC;CACpB;AAkDD,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKzE;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAStE;AAED,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBtG;AA2CD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBlF;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAY/D;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA0B7D;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAyBvG;AAsBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAoB/E;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAWhF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB3D;AAsED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAQxE"}
@@ -5,13 +5,19 @@ import { cliPackageVersion, isSmoothBricksCodebasePackageName } from '../lib/cli
5
5
  import { ensureDependencyMap, readJsonObject, setPackageStringField, setStringProperty, writeJsonObject, } from '../lib/json.js';
6
6
  import { readPackageJsonObject } from '../lib/workspace.js';
7
7
  const isRegistryPackument = (() => {
8
- const _io0 = input => "object" === typeof input.versions && null !== input.versions && false === Array.isArray(input.versions) && _io1(input.versions);
8
+ const _io0 = input => "object" === typeof input.versions && null !== input.versions && false === Array.isArray(input.versions) && _io1(input.versions) && (undefined === input["dist-tags"] || "object" === typeof input["dist-tags"] && null !== input["dist-tags"] && false === Array.isArray(input["dist-tags"]) && _io2(input["dist-tags"]));
9
9
  const _io1 = input => Object.keys(input).every(key => {
10
10
  const value = input[key];
11
11
  if (undefined === value)
12
12
  return true;
13
13
  return true;
14
14
  });
15
+ const _io2 = input => Object.keys(input).every(key => {
16
+ const value = input[key];
17
+ if (undefined === value)
18
+ return true;
19
+ return "string" === typeof value;
20
+ });
15
21
  return input => "object" === typeof input && null !== input && _io0(input);
16
22
  })();
17
23
  const rootDevDependencies = [
@@ -34,10 +40,14 @@ const rootDevDependencies = [
34
40
  },
35
41
  { name: 'nx', fallbackVersion: '23.1.0', minimumVersion: '23.1.0' },
36
42
  { name: 'prettier', fallbackVersion: '^3.6.1', minimumVersion: '3.6.0', prefix: '^' },
37
- { name: 'ttsc', fallbackVersion: '^0.18.4', minimumVersion: '0.18.4', prefix: '^' },
43
+ // Exact pin: Bun patchedDependencies keys are version-locked (see patches/ttsc@0.19.3.patch).
44
+ { name: 'ttsc', fallbackVersion: '0.19.3' },
38
45
  // Nx and typescript-eslint still load the TypeScript JS API (6.x).
39
46
  // Compilation is exclusively delegated to ttsc by the Nx plugin targets.
40
- { name: 'typescript', fallbackVersion: '^5.9.3', minimumVersion: '5.9.0', prefix: '^' },
47
+ { name: 'typescript', fallbackVersion: '^6.0.3', minimumVersion: '6.0.0', prefix: '^' },
48
+ // TS7 native compiler for ttsc (TTSC_TSGO_BINARY). Not the unscoped API package.
49
+ // npm alias form required — Bun cannot install @typescript/typescript6 cleanly (bun#33834).
50
+ { name: '@typescript/native', fallbackVersion: 'npm:typescript@^7.0.2' },
41
51
  ];
42
52
  const cliPackageName = '@smoothbricks/cli';
43
53
  const requiredDevenvPackages = ['bun', 'git', 'git-format-staged', 'jq', 'alejandra', 'coreutils', 'gnutar'];
@@ -46,15 +56,18 @@ const requiredDevenvPackages = ['bun', 'git', 'git-format-staged', 'jq', 'alejan
46
56
  // with the runtime is validated against the live PATH (validateRootRuntimeVersions),
47
57
  // never against a version template here.
48
58
  const nodePackagePattern = /(^|\s)nodejs(_\d+|_latest)?(\s|#|$)/m;
59
+ const TTSC_PATCHED_DEPENDENCY_KEY = 'ttsc@0.19.3';
60
+ const TTSC_PATCH_PATH = 'patches/ttsc@0.19.3.patch';
49
61
  export async function applyToolConfigDefaults(root) {
50
- const context = readToolContext(root);
62
+ const context = await readToolContext(root);
51
63
  await applyRootPackageToolDefaults(root, context);
52
64
  applyToolingPackageDefaults(root, context.policy);
53
65
  applyDevenvPackageDefaults(root);
54
66
  }
55
- export function validateToolConfig(root) {
56
- const context = readToolContext(root);
67
+ export async function validateToolConfig(root) {
68
+ const context = await readToolContext(root);
57
69
  return (validateRootDevDependencies(context.policy, context.rootPackage) +
70
+ validateTtscPatchedDependency(context.rootPackage) +
58
71
  validateToolingPackage(root, context.policy) +
59
72
  validateToolingWorkspace(context.rootPackage) +
60
73
  validateDevenvPackages(root));
@@ -76,6 +89,7 @@ export async function applyRootDevDependencyDefaults(root, context) {
76
89
  if (delete devDependencies['@smoothbricks/cli']) {
77
90
  changed = true;
78
91
  }
92
+ changed = ensureTtscPatchedDependency(pkg) || changed;
79
93
  if (changed) {
80
94
  writeJsonObject(join(root, 'package.json'), pkg);
81
95
  console.log('updated package.json workspace tool dependencies');
@@ -91,6 +105,7 @@ async function applyRootPackageToolDefaults(root, context) {
91
105
  }
92
106
  let dependencyChanged = false;
93
107
  let workspaceChanged = false;
108
+ let patchChanged = false;
94
109
  const devDependencies = ensureDependencyMap(pkg, 'devDependencies');
95
110
  for (const dependency of rootDevDependencies) {
96
111
  const current = devDependencies[dependency.name];
@@ -103,7 +118,8 @@ async function applyRootPackageToolDefaults(root, context) {
103
118
  dependencyChanged = true;
104
119
  }
105
120
  workspaceChanged = addWorkspacePattern(pkg, 'tooling');
106
- if (dependencyChanged || workspaceChanged) {
121
+ patchChanged = ensureTtscPatchedDependency(pkg);
122
+ if (dependencyChanged || workspaceChanged || patchChanged) {
107
123
  writeJsonObject(join(root, 'package.json'), pkg);
108
124
  }
109
125
  console.log(dependencyChanged
@@ -112,6 +128,9 @@ async function applyRootPackageToolDefaults(root, context) {
112
128
  console.log(workspaceChanged
113
129
  ? 'updated package.json tooling workspace'
114
130
  : 'unchanged package.json tooling workspace');
131
+ console.log(patchChanged
132
+ ? 'updated package.json patchedDependencies for ttsc'
133
+ : 'unchanged package.json patchedDependencies for ttsc');
115
134
  }
116
135
  export function applyToolingPackageDefaults(root, policy) {
117
136
  const path = join(root, 'tooling', 'package.json');
@@ -200,6 +219,22 @@ export function validateRootDevDependencies(policy, rootPackage) {
200
219
  }
201
220
  return failures;
202
221
  }
222
+ function ensureTtscPatchedDependency(pkg) {
223
+ const patched = ensureDependencyMap(pkg, 'patchedDependencies');
224
+ return setStringProperty(patched, TTSC_PATCHED_DEPENDENCY_KEY, TTSC_PATCH_PATH);
225
+ }
226
+ function validateTtscPatchedDependency(rootPackage) {
227
+ if (!rootPackage) {
228
+ return 0;
229
+ }
230
+ const actual = rootPackage.patchedDependencies?.[TTSC_PATCHED_DEPENDENCY_KEY];
231
+ if (actual === TTSC_PATCH_PATH) {
232
+ return 0;
233
+ }
234
+ console.error(`package.json patchedDependencies.${TTSC_PATCHED_DEPENDENCY_KEY} must be ${TTSC_PATCH_PATH}` +
235
+ (typeof actual === 'string' ? `; found ${actual}` : ' (required for declaration-emit fix)'));
236
+ return 1;
237
+ }
203
238
  export function validateToolingPackage(root, policy) {
204
239
  const path = join(root, 'tooling', 'package.json');
205
240
  const pkg = readJsonObject(path);
@@ -287,6 +322,10 @@ function satisfiesDependencyPolicy(policy, version, dependency) {
287
322
  if (workspaceDependencyExpected(policy, dependency)) {
288
323
  return version === 'workspace:*';
289
324
  }
325
+ // Dual-package native compiler: must stay an npm:typescript@7 alias, never unscoped "typescript".
326
+ if (dependency.name === '@typescript/native') {
327
+ return isTypeScriptNativeAlias(version);
328
+ }
290
329
  if (dependency.minimumVersion === undefined) {
291
330
  return version === dependency.fallbackVersion;
292
331
  }
@@ -297,34 +336,38 @@ function satisfiesDependencyPolicy(policy, version, dependency) {
297
336
  }
298
337
  return compareVersions(parsed, minimum) >= 0;
299
338
  }
339
+ function isTypeScriptNativeAlias(version) {
340
+ // Accept npm:typescript@7, npm:typescript@^7.0.2, npm:typescript@~7.0.2, etc.
341
+ return /^npm:typescript@(?:\^|~)?7(?:\.|$)/.test(version.trim());
342
+ }
300
343
  function formatExpectedDependency(policy, dependency) {
301
344
  if (workspaceDependencyExpected(policy, dependency)) {
302
345
  return 'workspace:*';
303
346
  }
347
+ if (dependency.name === '@typescript/native') {
348
+ return 'npm:typescript@^7 (TypeScript 7 native compiler alias for ttsc)';
349
+ }
304
350
  return dependency.minimumVersion ? `>= ${dependency.minimumVersion}` : dependency.fallbackVersion;
305
351
  }
306
- export function readToolContext(root) {
352
+ export async function readToolContext(root) {
307
353
  const rootPackage = readPackageJsonObject(join(root, 'package.json'));
308
354
  const toolingPackage = readJsonObject(join(root, 'tooling', 'package.json'));
309
355
  const configuredCliRange = toolingPackage?.dependencies?.[cliPackageName];
310
356
  return {
311
357
  rootPackage,
312
- policy: toolPolicy(rootPackage, typeof configuredCliRange === 'string' ? configuredCliRange : null),
358
+ policy: await toolPolicy(rootPackage, typeof configuredCliRange === 'string' ? configuredCliRange : null),
313
359
  };
314
360
  }
315
- function toolPolicy(rootPackage, configuredCliRange) {
361
+ async function toolPolicy(rootPackage, configuredCliRange) {
316
362
  const name = rootPackage?.name ?? null;
317
363
  const isCodebase = isSmoothBricksCodebasePackageName(name ?? undefined);
318
364
  const toolingName = toolingPackageName(name);
319
- // A locally linked prerelease can be newer than every published CLI. Keep an existing
320
- // installable range instead of rewriting the consumer manifest to an unpublished version.
321
- const publishedCliRange = cliPackageVersion.includes('-') && configuredCliRange && parseVersion(configuredCliRange)
322
- ? configuredCliRange
323
- : `^${cliPackageVersion}`;
324
365
  return {
325
366
  isSmoothBricksCodebase: isCodebase,
326
367
  toolingPackageName: toolingName,
327
- cliDependencyRange: isCodebase ? 'workspace:*' : publishedCliRange,
368
+ // Consumers pin the latest *published* CLI. Running a linked prerelease must not
369
+ // freeze tooling/package.json on an older range or rewrite it to an unpublished -next.
370
+ cliDependencyRange: isCodebase ? 'workspace:*' : await resolvePublishedCliDependencyRange(configuredCliRange),
328
371
  };
329
372
  }
330
373
  function toolingPackageName(rootName) {
@@ -345,6 +388,57 @@ async function resolveDependencyVersion(policy, dependency) {
345
388
  const latest = await fetchLatestPatchVersion(dependency.name, dependency.minimumVersion);
346
389
  return `${dependency.prefix ?? ''}${latest ?? stripRangePrefix(dependency.fallbackVersion)}`;
347
390
  }
391
+ /**
392
+ * Consumer monorepos pin `@smoothbricks/cli` to the latest stable release.
393
+ * Prefer npm `dist-tags.latest`. Never write a running `-next` package version into
394
+ * consumer manifests; never leave an older pin just because the running CLI is prerelease.
395
+ */
396
+ async function resolvePublishedCliDependencyRange(configuredCliRange) {
397
+ const latest = await fetchLatestStableVersion(cliPackageName);
398
+ if (latest) {
399
+ return `^${latest}`;
400
+ }
401
+ // Registry unavailable: if the running CLI is a stable publish, use it.
402
+ if (!cliPackageVersion.includes('-')) {
403
+ return `^${cliPackageVersion}`;
404
+ }
405
+ // Linked prerelease + offline down: keep an existing installable stable pin.
406
+ if (configuredCliRange && parseVersion(configuredCliRange)) {
407
+ return configuredCliRange;
408
+ }
409
+ // Last resort: caret of the prerelease base (0.10.5-next.0 → ^0.10.5) so manifests stay valid.
410
+ const base = parseVersion(cliPackageVersion);
411
+ return base ? `^${base.major}.${base.minor}.${base.patch}` : `^${cliPackageVersion}`;
412
+ }
413
+ async function fetchLatestStableVersion(packageName) {
414
+ const url = `https://registry.npmjs.org/${encodeURIComponent(packageName).replace('%40', '@')}`;
415
+ const response = await fetch(url, { headers: { accept: 'application/vnd.npm.install-v1+json' } });
416
+ if (!response.ok) {
417
+ return null;
418
+ }
419
+ const body = await response.json();
420
+ if (!isRegistryPackument(body)) {
421
+ return null;
422
+ }
423
+ const tagged = body['dist-tags']?.latest;
424
+ if (typeof tagged === 'string' && parseVersion(tagged) && !tagged.includes('-')) {
425
+ return tagged;
426
+ }
427
+ let latest = null;
428
+ for (const raw of Object.keys(body.versions)) {
429
+ if (raw.includes('-')) {
430
+ continue;
431
+ }
432
+ const version = parseVersion(raw);
433
+ if (!version) {
434
+ continue;
435
+ }
436
+ if (!latest || compareVersions(version, latest) > 0) {
437
+ latest = version;
438
+ }
439
+ }
440
+ return latest ? `${latest.major}.${latest.minor}.${latest.patch}` : null;
441
+ }
348
442
  async function fetchLatestPatchVersion(packageName, minimumVersion) {
349
443
  const minorRange = sameMajorMinorRange(minimumVersion);
350
444
  const url = `https://registry.npmjs.org/${encodeURIComponent(packageName).replace('%40', '@')}`;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ import { withDevenvEnv } from '../lib/devenv.js';
12
12
  import { parseNxJsonText, parseNxProjectJsonText, parsePackageJsonText, } from '../lib/json.js';
13
13
  import { decode, run, runInteractiveStatus, runResult } from '../lib/run.js';
14
14
  import { listReleasePackages, readPackageJson, repositoryInfo } from '../lib/workspace.js';
15
+ import { syncBunLockfileVersions } from '../monorepo/lockfile.js';
15
16
  import { readPackedPackageJson, validatePackedWorkspaceDependencies } from '../monorepo/packed-manifest.js';
16
17
  import { bootstrapNpmPackages, NPM_BOOTSTRAP_DIST_TAG, NPM_BOOTSTRAP_VERSION, } from './bootstrap-npm-packages.js';
17
18
  import { autoReleaseCandidatePackages } from './candidates.js';
@@ -301,6 +302,10 @@ async function listUnpublishedPackages(root, packages) {
301
302
  async function publishPackedPackage(root, pkg, tag, dryRun) {
302
303
  const tempDir = await mkdtemp(join(tmpdir(), 'smoo-publish-'));
303
304
  const tarball = join(tempDir, `${safeTarballPrefix(pkg.name)}-${pkg.version}.tgz`);
305
+ // bun pm pack resolves workspace:* from bun.lock. Day-to-day lock keeps -next
306
+ // (install/CI). For publish, temporarily rewrite unpublished -next entries to
307
+ // the last stable tag so the tarball embeds installable versions, then restore.
308
+ syncBunLockfileVersions(root, { mode: 'publish', log: true });
304
309
  try {
305
310
  console.log(`${pkg.name}@${pkg.version}: packing with bun pm pack`);
306
311
  await run('bun', ['pm', 'pack', '--filename', tarball, '--ignore-scripts', '--quiet'], join(root, pkg.path));
@@ -329,6 +334,7 @@ async function publishPackedPackage(root, pkg, tag, dryRun) {
329
334
  });
330
335
  }
331
336
  finally {
337
+ syncBunLockfileVersions(root, { mode: 'install', log: true });
332
338
  await rm(tempDir, { recursive: true, force: true });
333
339
  }
334
340
  }
package/managed/raw/envrc CHANGED
@@ -11,8 +11,10 @@ esac
11
11
 
12
12
  watch_file tooling/direnv/envrc.sh
13
13
 
14
+ # Load local extensions and overrides from the project root (the gitignored
15
+ # .envrc-local); capture it before we cd into tooling/direnv, since envrc.sh
16
+ # leaves us there and a bare relative path would resolve under tooling/direnv.
17
+ local_override="$PWD/.envrc-local"
14
18
  cd tooling/direnv
15
19
  . envrc.sh
16
-
17
- # Load local extensions and overrides
18
- source_env_if_exists .envrc-local
20
+ source_env_if_exists "$local_override"
@@ -0,0 +1,67 @@
1
+ --- a/driver/emit_plugin.go
2
+ +++ b/driver/emit_plugin.go
3
+ @@ -163,6 +163,32 @@
4
+ }
5
+ host := &pluginEmitHost{program: p.TSProgram, emitResolver: p.Checker.GetEmitResolver()}
6
+ options := p.TSProgram.Options()
7
+ + // Declaration emit must observe the original program before plugin transforms
8
+ + // can mutate source-file nodes while assembling JavaScript output.
9
+ + if options.GetEmitDeclarations() {
10
+ + var wfMu sync.Mutex
11
+ + result := p.TSProgram.Emit(context.Background(), shimcompiler.EmitOptions{
12
+ + EmitOnly: shimcompiler.EmitOnlyDts,
13
+ + WriteFile: func(fileName string, text string, data *shimcompiler.WriteFileData) error {
14
+ + wfMu.Lock()
15
+ + defer wfMu.Unlock()
16
+ + if p.outputEscapesOutDir(fileName) {
17
+ + if data != nil {
18
+ + data.SkippedDtsWrite = true
19
+ + }
20
+ + return nil
21
+ + }
22
+ + if writeFile != nil {
23
+ + return writeFile(fileName, text, data)
24
+ + }
25
+ + return DefaultWriteFile(fileName, text)
26
+ + },
27
+ + })
28
+ + if result != nil && len(result.Diagnostics) != 0 {
29
+ + return convertDiagnostics(result.Diagnostics), nil
30
+ + }
31
+ + }
32
+ +
33
+ for _, sf := range shimcompiler.GetSourceFilesToEmit(host, nil, false) {
34
+ paths := shimcompiler.GetOutputPathsFor(sf, options, host, false)
35
+ if paths.JsFilePath() != "" && !p.outputEscapesOutDir(paths.JsFilePath()) {
36
+ @@ -212,31 +238,6 @@
37
+ }
38
+ }
39
+ }
40
+ - if !options.GetEmitDeclarations() {
41
+ - return nil, nil
42
+ - }
43
+ -
44
+ - var wfMu sync.Mutex
45
+ - result := p.TSProgram.Emit(context.Background(), shimcompiler.EmitOptions{
46
+ - EmitOnly: shimcompiler.EmitOnlyDts,
47
+ - WriteFile: func(fileName string, text string, data *shimcompiler.WriteFileData) error {
48
+ - wfMu.Lock()
49
+ - defer wfMu.Unlock()
50
+ - if p.outputEscapesOutDir(fileName) {
51
+ - if data != nil {
52
+ - data.SkippedDtsWrite = true
53
+ - }
54
+ - return nil
55
+ - }
56
+ - if writeFile != nil {
57
+ - return writeFile(fileName, text, data)
58
+ - }
59
+ - return DefaultWriteFile(fileName, text)
60
+ - },
61
+ - })
62
+ - if result != nil && len(result.Diagnostics) != 0 {
63
+ - return convertDiagnostics(result.Diagnostics), nil
64
+ - }
65
+ return nil, nil
66
+ }
67
+
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { existsSync, mkdirSync, readdirSync, readlinkSync, rmSync, symlinkSync } from 'node:fs';
2
+ import { existsSync, mkdirSync, readdirSync, readFileSync, readlinkSync, rmSync, symlinkSync } from 'node:fs';
3
3
  import { mkdir, rmdir, stat } from 'node:fs/promises';
4
4
  import { createRequire } from 'node:module';
5
5
  import path from 'node:path';
@@ -98,8 +98,28 @@ function ensureTypeScriptApiPackage(root: string): void {
98
98
  assertTypescriptApiAt(path.join(root, 'node_modules', '.bun', 'node_modules', 'typescript'), apiPackageRoot);
99
99
 
100
100
  const nativeBin = path.join(root, 'node_modules', '@typescript', 'native', 'bin', 'tsc');
101
- if (!existsSync(nativeBin)) {
102
- throw new Error(`Missing ${nativeBin}. @typescript/native must remain the TypeScript 7 native compiler for ttsc.`);
101
+ const rootPackageJson = path.join(root, 'package.json');
102
+ const declaresNative =
103
+ existsSync(rootPackageJson) &&
104
+ (() => {
105
+ try {
106
+ const pkg = JSON.parse(readFileSync(rootPackageJson, 'utf8')) as {
107
+ devDependencies?: Record<string, string>;
108
+ dependencies?: Record<string, string>;
109
+ };
110
+ return (
111
+ typeof pkg.devDependencies?.['@typescript/native'] === 'string' ||
112
+ typeof pkg.dependencies?.['@typescript/native'] === 'string'
113
+ );
114
+ } catch {
115
+ return false;
116
+ }
117
+ })();
118
+ if (declaresNative && !existsSync(nativeBin)) {
119
+ throw new Error(
120
+ `Missing ${nativeBin}. package.json declares @typescript/native but it is not installed. ` +
121
+ 'Run bun install (or direnv reload). @typescript/native is the TypeScript 7 native compiler for ttsc.',
122
+ );
103
123
  }
104
124
  }
105
125
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smoothbricks/cli",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "type": "module",
5
5
  "description": "SmoothBricks monorepo automation CLI",
6
6
  "bin": {
@@ -64,7 +64,7 @@
64
64
  "dependencies": {
65
65
  "@arethetypeswrong/core": "^0.18.2",
66
66
  "@prettier/sync": "^0.6.1",
67
- "@smoothbricks/nx-plugin": "0.3.3",
67
+ "@smoothbricks/nx-plugin": "0.3.4",
68
68
  "@smoothbricks/validation": "0.1.4",
69
69
  "commander": "^14.0.3",
70
70
  "prettier": "^3.6.1",
package/src/cli.ts CHANGED
@@ -59,7 +59,7 @@ function buildProgram(): Command {
59
59
  );
60
60
  monorepo.command('update').action(async () => {
61
61
  const { updateManagedFiles } = await import('./monorepo/index.js');
62
- updateManagedFiles(await findRepoRoot());
62
+ await updateManagedFiles(await findRepoRoot());
63
63
  });
64
64
  monorepo
65
65
  .command('check')
@@ -84,12 +84,12 @@ function buildProgram(): Command {
84
84
  .option('--stage', 'stage bun.lock when versions were resynced; quiet when clean')
85
85
  .option(
86
86
  '--mode <mode>',
87
- 'install: match package.json (CI); publish: map unpublished -next to last stable tag (pre-pack)',
88
- 'publish',
87
+ 'install: match package.json (default, CI); publish: map unpublished -next to last stable tag (pre-pack only)',
88
+ 'install',
89
89
  )
90
90
  .action(async (options: { stage?: boolean; mode?: 'install' | 'publish' }) => {
91
91
  const { syncBunLockfileVersions } = await import('./monorepo/index.js');
92
- const mode = options.mode === 'install' ? 'install' : 'publish';
92
+ const mode = options.mode === 'publish' ? 'publish' : 'install';
93
93
  syncBunLockfileVersions(await findRepoRoot(), {
94
94
  mode,
95
95
  ...(options.stage ? { log: false, stage: true } : {}),
package/src/lib/json.ts CHANGED
@@ -52,6 +52,8 @@ export interface PackageJson {
52
52
  devDependencies?: StringMap;
53
53
  peerDependencies?: StringMap;
54
54
  optionalDependencies?: StringMap;
55
+ /** Bun patchedDependencies map (package@version → patch path). */
56
+ patchedDependencies?: StringMap;
55
57
  engines?: StringMap;
56
58
  scripts?: StringMap;
57
59
  publishConfig?: PackagePublishConfig;
@@ -165,7 +167,7 @@ export function ensureScripts(pkg: PackageJson): StringMap {
165
167
  /** Ensure package.json.dependencies (or other string-map dep field) exists. */
166
168
  export function ensureDependencyMap(
167
169
  pkg: PackageJson,
168
- key: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies',
170
+ key: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies' | 'patchedDependencies',
169
171
  ): StringMap {
170
172
  const current = pkg[key];
171
173
  if (isStringMap(current)) {
@@ -9,6 +9,7 @@ import { applyManagedFiles, printResults, warnOnManagedFileDrift } from './manag
9
9
  import { listValidCommitScopes, validatePublicTags } from './package-policy.js';
10
10
  import { runInitPacks, runValidatePacks } from './packs/index.js';
11
11
  import { syncRootRuntimeVersions } from './runtime.js';
12
+ import { applyToolConfigDefaults } from './tool-validation.js';
12
13
 
13
14
  export interface InitOptions {
14
15
  runtimeOnly?: boolean;
@@ -74,8 +75,19 @@ export async function validateMonorepo(root: string, options: ValidateOptions =
74
75
  }
75
76
  }
76
77
 
77
- export function updateManagedFiles(root: string): void {
78
+ export async function updateManagedFiles(root: string): Promise<void> {
78
79
  printResults(applyManagedFiles(root, 'update'));
80
+ // Tool dependency policy (typescript API 6, @typescript/native for ttsc, nx, …)
81
+ // lives next to managed templates — update must install them, not only rewrite files.
82
+ await applyToolConfigDefaults(root);
83
+ syncBunLockfileVersions(root, { mode: 'install' });
84
+ console.log('installing workspace dependencies (bun install)');
85
+ const install = await $`bun install --no-summary`.cwd(root).nothrow();
86
+ if (install.exitCode !== 0) {
87
+ const stderr = decode(install.stderr).trim();
88
+ const stdout = decode(install.stdout).trim();
89
+ throw new Error(`bun install failed after monorepo update${stderr || stdout ? `:\n${stderr || stdout}` : ''}`);
90
+ }
79
91
  }
80
92
 
81
93
  export function checkManagedFiles(root: string, options: { warn?: boolean } = {}): void {
@@ -8,9 +8,10 @@ export interface SyncBunLockfileVersionsOptions {
8
8
  /** `git add` bun.lock when versions were resynced. */
9
9
  stage?: boolean;
10
10
  /**
11
- * `install` (default for validation): lockfile must match package.json.
11
+ * `install` (default): lockfile must match package.json (including -next).
12
12
  * `publish`: rewrite unpublished prerelease package.json versions to the last
13
13
  * stable git tag so `bun pm pack` embeds installable dependency versions.
14
+ * Only use publish mode around pack; never leave the tree in publish mode.
14
15
  */
15
16
  mode?: 'install' | 'publish';
16
17
  }
@@ -34,7 +35,7 @@ export interface SyncBunLockfileVersionsOptions {
34
35
  // rewrites lockfile back to package.json and frozen CI then fails.
35
36
  export function syncBunLockfileVersions(root: string, options: SyncBunLockfileVersionsOptions = {}): number {
36
37
  const log = options.log ?? true;
37
- const mode = options.mode ?? 'publish';
38
+ const mode = options.mode ?? 'install';
38
39
  const lockfilePath = join(root, 'bun.lock');
39
40
  if (!existsSync(lockfilePath)) {
40
41
  throw new Error('bun.lock not found');
@@ -199,6 +199,11 @@ const managedFiles: ManagedFile[] = [
199
199
  target: 'tooling/direnv/merge-newer-pins.sh',
200
200
  executable: true,
201
201
  },
202
+ {
203
+ kind: 'raw',
204
+ source: 'patches/ttsc@0.19.3.patch',
205
+ target: 'patches/ttsc@0.19.3.patch',
206
+ },
202
207
  {
203
208
  kind: 'generated',
204
209
  source: 'ci-workflow',
@@ -96,7 +96,7 @@ const packs: MonorepoPack[] = [
96
96
  return (
97
97
  runtimeFailures +
98
98
  validateRootPackagePolicy(ctx.root) +
99
- validateToolConfig(ctx.root) +
99
+ (await validateToolConfig(ctx.root)) +
100
100
  validateNxProjectNames(ctx.root) +
101
101
  validateNxReleaseConfig(ctx.root) +
102
102
  validateBunLockfileVersions(ctx.root) +
@@ -13,13 +13,20 @@ import {
13
13
  const registryVersions: Record<string, string[]> = {
14
14
  '@biomejs/biome': ['2.3.5'],
15
15
  '@nx/js': ['23.1.0'],
16
+ '@smoothbricks/cli': ['0.10.3', '0.10.4'],
16
17
  '@smoothbricks/nx-plugin': ['0.3.0'],
17
18
  eslint: ['9.39.1'],
18
19
  'eslint-stdout': ['1.1.1', '1.1.2'],
19
20
  nx: ['23.1.0'],
20
21
  prettier: ['3.6.1'],
21
- ttsc: ['0.18.4'],
22
- typescript: ['5.9.3'],
22
+ ttsc: ['0.19.3'],
23
+ typescript: ['6.0.3'],
24
+ // alias package is not fetched from registry under this name when using fallback
25
+ '@typescript/native': ['7.0.2'],
26
+ };
27
+
28
+ const registryLatestTags: Record<string, string> = {
29
+ '@smoothbricks/cli': '0.10.4',
23
30
  };
24
31
 
25
32
  const realFetch = globalThis.fetch;
@@ -58,9 +65,9 @@ describe('tool configuration validation', () => {
58
65
  `,
59
66
  );
60
67
 
61
- expect(validateToolConfig(root)).toBeGreaterThan(0);
68
+ expect(await validateToolConfig(root)).toBeGreaterThan(0);
62
69
  await applyToolConfigDefaults(root);
63
- expect(validateToolConfig(root)).toBe(0);
70
+ expect(await validateToolConfig(root)).toBe(0);
64
71
 
65
72
  const rootPackage = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
66
73
  const toolingPackage = JSON.parse(await readFile(join(root, 'tooling/package.json'), 'utf8'));
@@ -69,6 +76,10 @@ describe('tool configuration validation', () => {
69
76
  expect(rootPackage.devDependencies['@smoothbricks/nx-plugin']).toBe('workspace:*');
70
77
  expect(rootPackage.devDependencies['eslint-stdout']).toBe('workspace:*');
71
78
  expect(rootPackage.devDependencies.nx).toBe('23.1.0');
79
+ expect(rootPackage.devDependencies.ttsc).toBe('0.19.3');
80
+ expect(rootPackage.devDependencies.typescript).toBe('^6.0.3');
81
+ expect(rootPackage.devDependencies['@typescript/native']).toBe('npm:typescript@^7.0.2');
82
+ expect(rootPackage.patchedDependencies['ttsc@0.19.3']).toBe('patches/ttsc@0.19.3.patch');
72
83
  expect(rootPackage.workspaces).toContain('tooling');
73
84
  expect(toolingPackage.name).toBe('@smoothbricks/tooling');
74
85
  expect(toolingPackage.dependencies['@smoothbricks/cli']).toBe('workspace:*');
@@ -97,8 +108,12 @@ describe('tool configuration validation', () => {
97
108
  'eslint-stdout': await currentEslintStdoutRange(),
98
109
  nx: '24.0.0',
99
110
  prettier: '^3.7.0',
100
- ttsc: '^0.19.0',
111
+ ttsc: '0.19.3',
101
112
  typescript: '^6.0.0',
113
+ '@typescript/native': 'npm:typescript@^7.0.2',
114
+ },
115
+ patchedDependencies: {
116
+ 'ttsc@0.19.3': 'patches/ttsc@0.19.3.patch',
102
117
  },
103
118
  });
104
119
  await writeJson(join(root, 'tooling/package.json'), {
@@ -128,18 +143,17 @@ describe('tool configuration validation', () => {
128
143
  `,
129
144
  );
130
145
 
131
- expect(validateToolConfig(root)).toBe(0);
146
+ expect(await validateToolConfig(root)).toBe(0);
132
147
  } finally {
133
148
  await rm(root, { recursive: true, force: true });
134
149
  }
135
150
  });
136
151
 
137
- it('preserves an installable CLI range when the running CLI is a linked prerelease', async () => {
152
+ it('bumps consumer CLI pin to npm latest even when the running CLI is a linked prerelease', async () => {
138
153
  const root = await mkdtemp(join(tmpdir(), 'smoo-tool-validation-'));
139
154
  try {
140
155
  const configuredRange = '^0.10.1';
141
- const runningRange = await currentCliRange();
142
- const expectedRange = runningRange.includes('-') ? configuredRange : runningRange;
156
+ const expectedRange = `^${registryLatestTags['@smoothbricks/cli']}`;
143
157
  await writeJson(join(root, 'package.json'), {
144
158
  name: '@fixture/app',
145
159
  version: '0.0.0',
@@ -152,7 +166,7 @@ describe('tool configuration validation', () => {
152
166
  dependencies: { '@smoothbricks/cli': configuredRange },
153
167
  });
154
168
 
155
- const context = readToolContext(root);
169
+ const context = await readToolContext(root);
156
170
  expect(context.policy.cliDependencyRange).toBe(expectedRange);
157
171
  applyToolingPackageDefaults(root, context.policy);
158
172
 
@@ -172,7 +186,7 @@ describe('tool configuration validation', () => {
172
186
  private: true,
173
187
  workspaces: ['packages/*', 'tooling'],
174
188
  });
175
- applyToolingPackageDefaults(root, readToolContext(root).policy);
189
+ applyToolingPackageDefaults(root, (await readToolContext(root)).policy);
176
190
 
177
191
  const toolingPackage = JSON.parse(await readFile(join(root, 'tooling/package.json'), 'utf8'));
178
192
  expect(toolingPackage.name).toBe('@smoothbricks/tooling');
@@ -196,12 +210,12 @@ describe('tool configuration validation', () => {
196
210
  eslint: '^10.0.0',
197
211
  nx: '24.0.0',
198
212
  prettier: '^3.7.0',
199
- ttsc: '^0.19.0',
213
+ ttsc: '0.19.3',
200
214
  typescript: '^6.0.0',
201
215
  },
202
216
  });
203
217
 
204
- const context = readToolContext(root);
218
+ const context = await readToolContext(root);
205
219
  await applyRootDevDependencyDefaults(root, context);
206
220
  applyToolingPackageDefaults(root, context.policy);
207
221
 
@@ -209,6 +223,8 @@ describe('tool configuration validation', () => {
209
223
  const toolingPackage = JSON.parse(await readFile(join(root, 'tooling/package.json'), 'utf8'));
210
224
  expect(rootPackage.devDependencies['eslint-stdout']).toBe(await currentEslintStdoutRange());
211
225
  expect(rootPackage.devDependencies['@smoothbricks/nx-plugin']).toBe(await currentNxPluginRange());
226
+ expect(rootPackage.devDependencies['@typescript/native']).toBe('npm:typescript@^7.0.2');
227
+ expect(rootPackage.patchedDependencies?.['ttsc@0.19.3']).toBe('patches/ttsc@0.19.3.patch');
212
228
  expect(toolingPackage.name).toBe('@fixture/tooling');
213
229
  expect(toolingPackage.dependencies['@smoothbricks/cli']).toBe(await currentCliRange());
214
230
  } finally {
@@ -218,8 +234,7 @@ describe('tool configuration validation', () => {
218
234
  });
219
235
 
220
236
  async function currentCliRange(): Promise<string> {
221
- const pkg = JSON.parse(await readFile(new URL('../../package.json', import.meta.url), 'utf8'));
222
- return `^${pkg.version}`;
237
+ return `^${registryLatestTags['@smoothbricks/cli']}`;
223
238
  }
224
239
 
225
240
  async function currentEslintStdoutRange(): Promise<string> {
@@ -235,8 +250,15 @@ const mockRegistryFetch = Object.assign(
235
250
  if (!versions) {
236
251
  return Promise.resolve(new Response('{}', { status: 404 }));
237
252
  }
253
+ const body: Record<string, unknown> = {
254
+ versions: Object.fromEntries(versions.map((version) => [version, {}])),
255
+ };
256
+ const latest = registryLatestTags[packageName];
257
+ if (latest) {
258
+ body['dist-tags'] = { latest };
259
+ }
238
260
  return Promise.resolve(
239
- new Response(JSON.stringify({ versions: Object.fromEntries(versions.map((version) => [version, {}])) }), {
261
+ new Response(JSON.stringify(body), {
240
262
  status: 200,
241
263
  headers: { 'content-type': 'application/json' },
242
264
  }),
@@ -32,6 +32,7 @@ export interface ToolContext {
32
32
 
33
33
  interface RegistryPackument {
34
34
  versions: Record<string, unknown>;
35
+ 'dist-tags'?: Record<string, string>;
35
36
  }
36
37
 
37
38
  const isRegistryPackument = typia.createIs<RegistryPackument>();
@@ -55,10 +56,14 @@ const rootDevDependencies: RequiredDependency[] = [
55
56
  },
56
57
  { name: 'nx', fallbackVersion: '23.1.0', minimumVersion: '23.1.0' },
57
58
  { name: 'prettier', fallbackVersion: '^3.6.1', minimumVersion: '3.6.0', prefix: '^' },
58
- { name: 'ttsc', fallbackVersion: '^0.18.4', minimumVersion: '0.18.4', prefix: '^' },
59
+ // Exact pin: Bun patchedDependencies keys are version-locked (see patches/ttsc@0.19.3.patch).
60
+ { name: 'ttsc', fallbackVersion: '0.19.3' },
59
61
  // Nx and typescript-eslint still load the TypeScript JS API (6.x).
60
62
  // Compilation is exclusively delegated to ttsc by the Nx plugin targets.
61
- { name: 'typescript', fallbackVersion: '^5.9.3', minimumVersion: '5.9.0', prefix: '^' },
63
+ { name: 'typescript', fallbackVersion: '^6.0.3', minimumVersion: '6.0.0', prefix: '^' },
64
+ // TS7 native compiler for ttsc (TTSC_TSGO_BINARY). Not the unscoped API package.
65
+ // npm alias form required — Bun cannot install @typescript/typescript6 cleanly (bun#33834).
66
+ { name: '@typescript/native', fallbackVersion: 'npm:typescript@^7.0.2' },
62
67
  ];
63
68
 
64
69
  const cliPackageName = '@smoothbricks/cli';
@@ -70,17 +75,21 @@ const requiredDevenvPackages = ['bun', 'git', 'git-format-staged', 'jq', 'alejan
70
75
  // never against a version template here.
71
76
  const nodePackagePattern = /(^|\s)nodejs(_\d+|_latest)?(\s|#|$)/m;
72
77
 
78
+ const TTSC_PATCHED_DEPENDENCY_KEY = 'ttsc@0.19.3';
79
+ const TTSC_PATCH_PATH = 'patches/ttsc@0.19.3.patch';
80
+
73
81
  export async function applyToolConfigDefaults(root: string): Promise<void> {
74
- const context = readToolContext(root);
82
+ const context = await readToolContext(root);
75
83
  await applyRootPackageToolDefaults(root, context);
76
84
  applyToolingPackageDefaults(root, context.policy);
77
85
  applyDevenvPackageDefaults(root);
78
86
  }
79
87
 
80
- export function validateToolConfig(root: string): number {
81
- const context = readToolContext(root);
88
+ export async function validateToolConfig(root: string): Promise<number> {
89
+ const context = await readToolContext(root);
82
90
  return (
83
91
  validateRootDevDependencies(context.policy, context.rootPackage) +
92
+ validateTtscPatchedDependency(context.rootPackage) +
84
93
  validateToolingPackage(root, context.policy) +
85
94
  validateToolingWorkspace(context.rootPackage) +
86
95
  validateDevenvPackages(root)
@@ -104,6 +113,7 @@ export async function applyRootDevDependencyDefaults(root: string, context: Tool
104
113
  if (delete devDependencies['@smoothbricks/cli']) {
105
114
  changed = true;
106
115
  }
116
+ changed = ensureTtscPatchedDependency(pkg) || changed;
107
117
  if (changed) {
108
118
  writeJsonObject(join(root, 'package.json'), pkg);
109
119
  console.log('updated package.json workspace tool dependencies');
@@ -119,6 +129,7 @@ async function applyRootPackageToolDefaults(root: string, context: ToolContext):
119
129
  }
120
130
  let dependencyChanged = false;
121
131
  let workspaceChanged = false;
132
+ let patchChanged = false;
122
133
  const devDependencies = ensureDependencyMap(pkg, 'devDependencies');
123
134
  for (const dependency of rootDevDependencies) {
124
135
  const current = devDependencies[dependency.name];
@@ -131,7 +142,8 @@ async function applyRootPackageToolDefaults(root: string, context: ToolContext):
131
142
  dependencyChanged = true;
132
143
  }
133
144
  workspaceChanged = addWorkspacePattern(pkg, 'tooling');
134
- if (dependencyChanged || workspaceChanged) {
145
+ patchChanged = ensureTtscPatchedDependency(pkg);
146
+ if (dependencyChanged || workspaceChanged || patchChanged) {
135
147
  writeJsonObject(join(root, 'package.json'), pkg);
136
148
  }
137
149
  console.log(
@@ -144,6 +156,11 @@ async function applyRootPackageToolDefaults(root: string, context: ToolContext):
144
156
  ? 'updated package.json tooling workspace'
145
157
  : 'unchanged package.json tooling workspace',
146
158
  );
159
+ console.log(
160
+ patchChanged
161
+ ? 'updated package.json patchedDependencies for ttsc'
162
+ : 'unchanged package.json patchedDependencies for ttsc',
163
+ );
147
164
  }
148
165
 
149
166
  export function applyToolingPackageDefaults(root: string, policy: ToolPolicy): void {
@@ -235,6 +252,26 @@ export function validateRootDevDependencies(policy: ToolPolicy, rootPackage: Pac
235
252
  return failures;
236
253
  }
237
254
 
255
+ function ensureTtscPatchedDependency(pkg: PackageJson): boolean {
256
+ const patched = ensureDependencyMap(pkg, 'patchedDependencies');
257
+ return setStringProperty(patched, TTSC_PATCHED_DEPENDENCY_KEY, TTSC_PATCH_PATH);
258
+ }
259
+
260
+ function validateTtscPatchedDependency(rootPackage: PackageJson | null): number {
261
+ if (!rootPackage) {
262
+ return 0;
263
+ }
264
+ const actual = rootPackage.patchedDependencies?.[TTSC_PATCHED_DEPENDENCY_KEY];
265
+ if (actual === TTSC_PATCH_PATH) {
266
+ return 0;
267
+ }
268
+ console.error(
269
+ `package.json patchedDependencies.${TTSC_PATCHED_DEPENDENCY_KEY} must be ${TTSC_PATCH_PATH}` +
270
+ (typeof actual === 'string' ? `; found ${actual}` : ' (required for declaration-emit fix)'),
271
+ );
272
+ return 1;
273
+ }
274
+
238
275
  export function validateToolingPackage(root: string, policy: ToolPolicy): number {
239
276
  const path = join(root, 'tooling', 'package.json');
240
277
  const pkg = readJsonObject(path);
@@ -331,6 +368,10 @@ function satisfiesDependencyPolicy(policy: ToolPolicy, version: string, dependen
331
368
  if (workspaceDependencyExpected(policy, dependency)) {
332
369
  return version === 'workspace:*';
333
370
  }
371
+ // Dual-package native compiler: must stay an npm:typescript@7 alias, never unscoped "typescript".
372
+ if (dependency.name === '@typescript/native') {
373
+ return isTypeScriptNativeAlias(version);
374
+ }
334
375
  if (dependency.minimumVersion === undefined) {
335
376
  return version === dependency.fallbackVersion;
336
377
  }
@@ -342,37 +383,41 @@ function satisfiesDependencyPolicy(policy: ToolPolicy, version: string, dependen
342
383
  return compareVersions(parsed, minimum) >= 0;
343
384
  }
344
385
 
386
+ function isTypeScriptNativeAlias(version: string): boolean {
387
+ // Accept npm:typescript@7, npm:typescript@^7.0.2, npm:typescript@~7.0.2, etc.
388
+ return /^npm:typescript@(?:\^|~)?7(?:\.|$)/.test(version.trim());
389
+ }
390
+
345
391
  function formatExpectedDependency(policy: ToolPolicy, dependency: RequiredDependency): string {
346
392
  if (workspaceDependencyExpected(policy, dependency)) {
347
393
  return 'workspace:*';
348
394
  }
395
+ if (dependency.name === '@typescript/native') {
396
+ return 'npm:typescript@^7 (TypeScript 7 native compiler alias for ttsc)';
397
+ }
349
398
  return dependency.minimumVersion ? `>= ${dependency.minimumVersion}` : dependency.fallbackVersion;
350
399
  }
351
400
 
352
- export function readToolContext(root: string): ToolContext {
401
+ export async function readToolContext(root: string): Promise<ToolContext> {
353
402
  const rootPackage = readPackageJsonObject(join(root, 'package.json'));
354
403
  const toolingPackage = readJsonObject(join(root, 'tooling', 'package.json'));
355
404
  const configuredCliRange = toolingPackage?.dependencies?.[cliPackageName];
356
405
  return {
357
406
  rootPackage,
358
- policy: toolPolicy(rootPackage, typeof configuredCliRange === 'string' ? configuredCliRange : null),
407
+ policy: await toolPolicy(rootPackage, typeof configuredCliRange === 'string' ? configuredCliRange : null),
359
408
  };
360
409
  }
361
410
 
362
- function toolPolicy(rootPackage: PackageJson | null, configuredCliRange: string | null): ToolPolicy {
411
+ async function toolPolicy(rootPackage: PackageJson | null, configuredCliRange: string | null): Promise<ToolPolicy> {
363
412
  const name = rootPackage?.name ?? null;
364
413
  const isCodebase = isSmoothBricksCodebasePackageName(name ?? undefined);
365
414
  const toolingName = toolingPackageName(name);
366
- // A locally linked prerelease can be newer than every published CLI. Keep an existing
367
- // installable range instead of rewriting the consumer manifest to an unpublished version.
368
- const publishedCliRange =
369
- cliPackageVersion.includes('-') && configuredCliRange && parseVersion(configuredCliRange)
370
- ? configuredCliRange
371
- : `^${cliPackageVersion}`;
372
415
  return {
373
416
  isSmoothBricksCodebase: isCodebase,
374
417
  toolingPackageName: toolingName,
375
- cliDependencyRange: isCodebase ? 'workspace:*' : publishedCliRange,
418
+ // Consumers pin the latest *published* CLI. Running a linked prerelease must not
419
+ // freeze tooling/package.json on an older range or rewrite it to an unpublished -next.
420
+ cliDependencyRange: isCodebase ? 'workspace:*' : await resolvePublishedCliDependencyRange(configuredCliRange),
376
421
  };
377
422
  }
378
423
 
@@ -397,6 +442,59 @@ async function resolveDependencyVersion(policy: ToolPolicy, dependency: Required
397
442
  return `${dependency.prefix ?? ''}${latest ?? stripRangePrefix(dependency.fallbackVersion)}`;
398
443
  }
399
444
 
445
+ /**
446
+ * Consumer monorepos pin `@smoothbricks/cli` to the latest stable release.
447
+ * Prefer npm `dist-tags.latest`. Never write a running `-next` package version into
448
+ * consumer manifests; never leave an older pin just because the running CLI is prerelease.
449
+ */
450
+ async function resolvePublishedCliDependencyRange(configuredCliRange: string | null): Promise<string> {
451
+ const latest = await fetchLatestStableVersion(cliPackageName);
452
+ if (latest) {
453
+ return `^${latest}`;
454
+ }
455
+ // Registry unavailable: if the running CLI is a stable publish, use it.
456
+ if (!cliPackageVersion.includes('-')) {
457
+ return `^${cliPackageVersion}`;
458
+ }
459
+ // Linked prerelease + offline down: keep an existing installable stable pin.
460
+ if (configuredCliRange && parseVersion(configuredCliRange)) {
461
+ return configuredCliRange;
462
+ }
463
+ // Last resort: caret of the prerelease base (0.10.5-next.0 → ^0.10.5) so manifests stay valid.
464
+ const base = parseVersion(cliPackageVersion);
465
+ return base ? `^${base.major}.${base.minor}.${base.patch}` : `^${cliPackageVersion}`;
466
+ }
467
+
468
+ async function fetchLatestStableVersion(packageName: string): Promise<string | null> {
469
+ const url = `https://registry.npmjs.org/${encodeURIComponent(packageName).replace('%40', '@')}`;
470
+ const response = await fetch(url, { headers: { accept: 'application/vnd.npm.install-v1+json' } });
471
+ if (!response.ok) {
472
+ return null;
473
+ }
474
+ const body: unknown = await response.json();
475
+ if (!isRegistryPackument(body)) {
476
+ return null;
477
+ }
478
+ const tagged = body['dist-tags']?.latest;
479
+ if (typeof tagged === 'string' && parseVersion(tagged) && !tagged.includes('-')) {
480
+ return tagged;
481
+ }
482
+ let latest: Version | null = null;
483
+ for (const raw of Object.keys(body.versions)) {
484
+ if (raw.includes('-')) {
485
+ continue;
486
+ }
487
+ const version = parseVersion(raw);
488
+ if (!version) {
489
+ continue;
490
+ }
491
+ if (!latest || compareVersions(version, latest) > 0) {
492
+ latest = version;
493
+ }
494
+ }
495
+ return latest ? `${latest.major}.${latest.minor}.${latest.patch}` : null;
496
+ }
497
+
400
498
  async function fetchLatestPatchVersion(packageName: string, minimumVersion: string): Promise<string | null> {
401
499
  const minorRange = sameMajorMinorRange(minimumVersion);
402
500
  const url = `https://registry.npmjs.org/${encodeURIComponent(packageName).replace('%40', '@')}`;
@@ -20,6 +20,7 @@ import {
20
20
  } from '../lib/json.js';
21
21
  import { decode, run, runInteractiveStatus, runResult } from '../lib/run.js';
22
22
  import { listReleasePackages, readPackageJson, repositoryInfo } from '../lib/workspace.js';
23
+ import { syncBunLockfileVersions } from '../monorepo/lockfile.js';
23
24
  import { readPackedPackageJson, validatePackedWorkspaceDependencies } from '../monorepo/packed-manifest.js';
24
25
  import {
25
26
  type BootstrapNpmPackagesOptions,
@@ -529,6 +530,10 @@ async function listUnpublishedPackages(root: string, packages: ReleasePackage[])
529
530
  async function publishPackedPackage(root: string, pkg: ReleasePackage, tag: string, dryRun: boolean): Promise<void> {
530
531
  const tempDir = await mkdtemp(join(tmpdir(), 'smoo-publish-'));
531
532
  const tarball = join(tempDir, `${safeTarballPrefix(pkg.name)}-${pkg.version}.tgz`);
533
+ // bun pm pack resolves workspace:* from bun.lock. Day-to-day lock keeps -next
534
+ // (install/CI). For publish, temporarily rewrite unpublished -next entries to
535
+ // the last stable tag so the tarball embeds installable versions, then restore.
536
+ syncBunLockfileVersions(root, { mode: 'publish', log: true });
532
537
  try {
533
538
  console.log(`${pkg.name}@${pkg.version}: packing with bun pm pack`);
534
539
  await run('bun', ['pm', 'pack', '--filename', tarball, '--ignore-scripts', '--quiet'], join(root, pkg.path));
@@ -560,6 +565,7 @@ async function publishPackedPackage(root: string, pkg: ReleasePackage, tag: stri
560
565
  },
561
566
  );
562
567
  } finally {
568
+ syncBunLockfileVersions(root, { mode: 'install', log: true });
563
569
  await rm(tempDir, { recursive: true, force: true });
564
570
  }
565
571
  }