@smoothbricks/cli 0.10.2 โ†’ 0.10.4

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 (133) hide show
  1. package/README.md +31 -23
  2. package/dist/bun/preload.d.ts +13 -0
  3. package/dist/bun/preload.d.ts.map +1 -0
  4. package/dist/bun/preload.js +12 -0
  5. package/dist/cli.js +36 -4
  6. package/dist/generate/index.d.ts.map +1 -1
  7. package/dist/generate/index.js +0 -6
  8. package/dist/github-ci/index.d.ts +17 -2
  9. package/dist/github-ci/index.d.ts.map +1 -1
  10. package/dist/github-ci/index.js +192 -26
  11. package/dist/github-ci/outputs.d.ts +22 -0
  12. package/dist/github-ci/outputs.d.ts.map +1 -0
  13. package/dist/github-ci/outputs.js +648 -0
  14. package/dist/lib/cli-package.js +2 -2
  15. package/dist/lib/json.d.ts +118 -11
  16. package/dist/lib/json.d.ts.map +1 -1
  17. package/dist/lib/json.js +317 -29
  18. package/dist/lib/workspace.d.ts +7 -14
  19. package/dist/lib/workspace.d.ts.map +1 -1
  20. package/dist/lib/workspace.js +76 -82
  21. package/dist/monorepo/ci-workflow.d.ts +2 -0
  22. package/dist/monorepo/ci-workflow.d.ts.map +1 -1
  23. package/dist/monorepo/ci-workflow.js +28 -2
  24. package/dist/monorepo/git-config.js +2 -2
  25. package/dist/monorepo/index.d.ts +3 -1
  26. package/dist/monorepo/index.d.ts.map +1 -1
  27. package/dist/monorepo/index.js +6 -2
  28. package/dist/monorepo/lockfile.d.ts +13 -1
  29. package/dist/monorepo/lockfile.d.ts.map +1 -1
  30. package/dist/monorepo/lockfile.js +33 -21
  31. package/dist/monorepo/managed-files.d.ts +12 -0
  32. package/dist/monorepo/managed-files.d.ts.map +1 -1
  33. package/dist/monorepo/managed-files.js +86 -28
  34. package/dist/monorepo/package-policy.d.ts.map +1 -1
  35. package/dist/monorepo/package-policy.js +78 -45
  36. package/dist/monorepo/packed-manifest.d.ts +5 -2
  37. package/dist/monorepo/packed-manifest.d.ts.map +1 -1
  38. package/dist/monorepo/packed-manifest.js +16 -47
  39. package/dist/monorepo/packed-package.d.ts.map +1 -1
  40. package/dist/monorepo/packed-package.js +28 -16
  41. package/dist/monorepo/packs/index.d.ts +3 -0
  42. package/dist/monorepo/packs/index.d.ts.map +1 -1
  43. package/dist/monorepo/packs/index.js +18 -6
  44. package/dist/monorepo/publish-workflow.d.ts +1 -0
  45. package/dist/monorepo/publish-workflow.d.ts.map +1 -1
  46. package/dist/monorepo/publish-workflow.js +242 -3
  47. package/dist/monorepo/runtime.d.ts +15 -0
  48. package/dist/monorepo/runtime.d.ts.map +1 -1
  49. package/dist/monorepo/runtime.js +66 -12
  50. package/dist/monorepo/tool-validation.d.ts.map +1 -1
  51. package/dist/monorepo/tool-validation.js +32 -23
  52. package/dist/monorepo/wrangler.d.ts.map +1 -1
  53. package/dist/monorepo/wrangler.js +13 -13
  54. package/dist/nx/index.d.ts +12 -4
  55. package/dist/nx/index.d.ts.map +1 -1
  56. package/dist/nx/index.js +86 -19
  57. package/dist/pr/index.d.ts.map +1 -1
  58. package/dist/pr/index.js +28 -32
  59. package/dist/release/candidates.d.ts +3 -2
  60. package/dist/release/candidates.d.ts.map +1 -1
  61. package/dist/release/candidates.js +4 -5
  62. package/dist/release/github-release.d.ts +3 -0
  63. package/dist/release/github-release.d.ts.map +1 -1
  64. package/dist/release/github-release.js +11 -0
  65. package/dist/release/index.d.ts +20 -1
  66. package/dist/release/index.d.ts.map +1 -1
  67. package/dist/release/index.js +221 -89
  68. package/dist/release/orchestration.d.ts +8 -1
  69. package/dist/release/orchestration.d.ts.map +1 -1
  70. package/dist/release/orchestration.js +38 -1
  71. package/dist/wrangler/prepare-env.d.ts +0 -1
  72. package/dist/wrangler/prepare-env.d.ts.map +1 -1
  73. package/dist/wrangler/prepare-env.js +100 -51
  74. package/dist/wrangler/scaffold.d.ts.map +1 -1
  75. package/dist/wrangler/scaffold.js +12 -12
  76. package/managed/raw/git-format-staged.yml +19 -1
  77. package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +6 -0
  78. package/managed/raw/tooling/direnv/merge-newer-pins.sh +3 -3
  79. package/managed/raw/tooling/direnv/setup-environment.ts +187 -19
  80. package/managed/raw/tooling/git-hooks/pre-commit.sh +0 -6
  81. package/managed/templates/github/actions/cache-nix-devenv/action.yml +12 -10
  82. package/managed/templates/github/actions/cache-node-modules/action.yml +6 -2
  83. package/managed/templates/github/actions/cache-nx/action.yml +2 -2
  84. package/managed/templates/github/actions/cache-ttsc-plugins/action.yml +19 -0
  85. package/managed/templates/github/actions/save-nix-devenv/action.yml +11 -3
  86. package/managed/templates/github/actions/setup-devenv/action.yml +5 -0
  87. package/managed/templates/github/workflows/managed-files.yml +80 -0
  88. package/package.json +18 -4
  89. package/src/bun/preload.ts +12 -0
  90. package/src/cli.ts +49 -11
  91. package/src/generate/index.ts +0 -6
  92. package/src/github-ci/index.test.ts +486 -0
  93. package/src/github-ci/index.ts +220 -30
  94. package/src/github-ci/outputs.ts +505 -0
  95. package/src/lib/cli-package.ts +2 -2
  96. package/src/lib/json.ts +291 -32
  97. package/src/lib/workspace.ts +88 -100
  98. package/src/monorepo/__tests__/ci-workflow.test.ts +14 -3
  99. package/src/monorepo/__tests__/publish-workflow.test.ts +222 -1
  100. package/src/monorepo/ci-workflow.ts +28 -2
  101. package/src/monorepo/git-config.ts +2 -2
  102. package/src/monorepo/index.ts +6 -2
  103. package/src/monorepo/lockfile.test.ts +35 -36
  104. package/src/monorepo/lockfile.ts +48 -24
  105. package/src/monorepo/managed-files.test.ts +63 -0
  106. package/src/monorepo/managed-files.ts +94 -34
  107. package/src/monorepo/package-policy.test.ts +70 -51
  108. package/src/monorepo/package-policy.ts +104 -59
  109. package/src/monorepo/packed-manifest.ts +18 -52
  110. package/src/monorepo/packed-package.ts +43 -22
  111. package/src/monorepo/packs/index.test.ts +18 -1
  112. package/src/monorepo/packs/index.ts +20 -7
  113. package/src/monorepo/publish-workflow.ts +482 -3
  114. package/src/monorepo/runtime.test.ts +42 -3
  115. package/src/monorepo/runtime.ts +90 -12
  116. package/src/monorepo/tool-validation.ts +35 -25
  117. package/src/monorepo/wrangler.test.ts +11 -15
  118. package/src/monorepo/wrangler.ts +15 -15
  119. package/src/nx/index.test.ts +43 -0
  120. package/src/nx/index.ts +110 -23
  121. package/src/pr/index.ts +42 -36
  122. package/src/release/__tests__/candidates.test.ts +5 -4
  123. package/src/release/__tests__/fixture-repo.test.ts +18 -16
  124. package/src/release/__tests__/github-release.test.ts +11 -0
  125. package/src/release/__tests__/orchestration.test.ts +57 -2
  126. package/src/release/__tests__/trust-publisher.test.ts +98 -2
  127. package/src/release/candidates.ts +10 -17
  128. package/src/release/github-release.ts +12 -0
  129. package/src/release/index.ts +321 -112
  130. package/src/release/orchestration.ts +55 -3
  131. package/src/wrangler/prepare-env.ts +75 -54
  132. package/src/wrangler/scaffold.test.ts +9 -12
  133. package/src/wrangler/scaffold.ts +13 -13
@@ -4,7 +4,8 @@ import { dirname, join, relative } from 'node:path';
4
4
  import { fileURLToPath, pathToFileURL } from 'node:url';
5
5
  import { publint } from 'publint';
6
6
  import { formatMessage } from 'publint/utils';
7
- import { isRecord } from '../lib/json.js';
7
+ import typia from 'typia';
8
+ import { parsePackageJsonText } from '../lib/json.js';
8
9
  import { printCommandOutput, runResult } from '../lib/run.js';
9
10
  import { listPublicPackages } from '../lib/workspace.js';
10
11
  import { readPackedPackageJson, validatePackedWorkspaceDependencies } from './packed-manifest.js';
@@ -60,7 +61,7 @@ async function validatePublint(_root, pkg, packed) {
60
61
  async function validatePackedManifest(root, pkg, packed) {
61
62
  let failures = 0;
62
63
  const packedPackage = await readPackedPackageJson(root, packed.path, pkg.name);
63
- for (const message of validatePackedWorkspaceDependencies(root, pkg, packedPackage)) {
64
+ for (const message of validatePackedWorkspaceDependencies(root, pkg, packedPackage, { mode: 'install' })) {
64
65
  console.error(message);
65
66
  failures++;
66
67
  }
@@ -71,11 +72,10 @@ async function validateAttw(root, pkg, packed) {
71
72
  const analysis = await attw.checkPackage(await createAttwPackageFromTarball(attw, root, packed.path), {
72
73
  excludeEntrypoints: nonJsExportEntrypoints(pkg.json.exports),
73
74
  });
74
- if (!isRecord(analysis) || analysis.types === false) {
75
+ if (!isAttwAnalysis(analysis) || analysis.types === false) {
75
76
  return 0;
76
77
  }
77
- const rawProblems = Array.isArray(analysis.problems) ? analysis.problems : [];
78
- const problems = rawProblems.filter(isReportedAttwProblem);
78
+ const problems = (analysis.problems ?? []).filter(isReportedAttwProblem);
79
79
  if (problems.length === 0) {
80
80
  return 0;
81
81
  }
@@ -85,10 +85,22 @@ async function validateAttw(root, pkg, packed) {
85
85
  console.error(`${pkg.path}: are-the-types-wrong validation failed`);
86
86
  return 1;
87
87
  }
88
+ const isAttwAnalysis = (() => {
89
+ const _io0 = input => true && (undefined === input.problems || Array.isArray(input.problems));
90
+ return input => "object" === typeof input && null !== input && false === Array.isArray(input) && _io0(input);
91
+ })();
92
+ const isAttwProblem = (() => {
93
+ const _io0 = input => "string" === typeof input.kind && (undefined === input.resolutionKind || "string" === typeof input.resolutionKind) && (undefined === input.entrypoint || "string" === typeof input.entrypoint);
94
+ return input => "object" === typeof input && null !== input && _io0(input);
95
+ })();
96
+ const isAttwCoreExport = (() => {
97
+ const _io0 = input => true && true;
98
+ return input => "object" === typeof input && null !== input && false === Array.isArray(input) && _io0(input);
99
+ })();
88
100
  async function loadAttwCore() {
89
101
  const packageJson = fileURLToPath(import.meta.resolve('@arethetypeswrong/core/package.json'));
90
102
  const core = await import(pathToFileURL(join(dirname(packageJson), 'dist', 'index.js')).href);
91
- if (!isRecord(core)) {
103
+ if (!isAttwCoreExport(core)) {
92
104
  throw new Error('@arethetypeswrong/core does not expose the expected API');
93
105
  }
94
106
  const PackageConstructor = core.Package;
@@ -117,8 +129,8 @@ async function createAttwPackageFromTarball(attw, root, tarballPath) {
117
129
  }
118
130
  function createAttwPackageFromDirectory(attw, packageDir) {
119
131
  const packageJson = readJsonFile(join(packageDir, 'package.json'));
120
- const packageName = typeof packageJson.name === 'string' ? packageJson.name : null;
121
- const packageVersion = typeof packageJson.version === 'string' ? packageJson.version : null;
132
+ const packageName = packageJson.name;
133
+ const packageVersion = packageJson.version;
122
134
  if (!packageName || !packageVersion) {
123
135
  throw new Error('packed package.json must contain name and version');
124
136
  }
@@ -142,14 +154,14 @@ function collectAttwFiles(root, current, packageName, files) {
142
154
  }
143
155
  }
144
156
  function readJsonFile(path) {
145
- const parsed = JSON.parse(readFileSync(path, 'utf8'));
146
- if (!isRecord(parsed)) {
157
+ const parsed = parsePackageJsonText(readFileSync(path, 'utf8'));
158
+ if (!parsed) {
147
159
  throw new Error(`${path} is not a JSON object`);
148
160
  }
149
161
  return parsed;
150
162
  }
151
163
  function isReportedAttwProblem(problem) {
152
- if (!isRecord(problem) || typeof problem.kind !== 'string') {
164
+ if (!isAttwProblem(problem)) {
153
165
  return false;
154
166
  }
155
167
  const flag = attwProblemFlag(problem.kind);
@@ -189,9 +201,6 @@ function attwProblemFlag(kind) {
189
201
  }
190
202
  }
191
203
  function formatProblemLocation(problem) {
192
- if (!isRecord(problem)) {
193
- return '';
194
- }
195
204
  const entrypoint = typeof problem.entrypoint === 'string' ? ` ${problem.entrypoint}` : '';
196
205
  const resolution = typeof problem.resolutionKind === 'string' ? ` ${formatResolutionKind(problem.resolutionKind)}` : '';
197
206
  return `${entrypoint}${resolution}`;
@@ -206,7 +215,7 @@ function formatResolutionKind(kind) {
206
215
  return kind;
207
216
  }
208
217
  function nonJsExportEntrypoints(exports) {
209
- if (!isRecord(exports)) {
218
+ if (exports === null || exports === undefined || typeof exports === 'string') {
210
219
  return [];
211
220
  }
212
221
  return Object.entries(exports)
@@ -219,7 +228,10 @@ function exportPointsToNonJs(value) {
219
228
  // Existence of the target files is still validated by publint.
220
229
  return value.endsWith('.wasm') || value.endsWith('.css');
221
230
  }
222
- return isRecord(value) && Object.values(value).some(exportPointsToNonJs);
231
+ if (value === null || value === undefined) {
232
+ return false;
233
+ }
234
+ return Object.values(value).some(exportPointsToNonJs);
223
235
  }
224
236
  async function packPackage(root, pkg) {
225
237
  const packageDir = join(root, pkg.path);
@@ -1,3 +1,5 @@
1
+ import { type ProjectTargets } from '../../nx/index.js';
2
+ import { type ResolvedProjectTargets } from '../package-policy.js';
1
3
  export interface MonorepoContext {
2
4
  root: string;
3
5
  syncRuntime: boolean;
@@ -26,4 +28,5 @@ export interface ValidatePackResult {
26
28
  }
27
29
  export declare function runInitPacks(ctx: MonorepoContext): Promise<void>;
28
30
  export declare function runValidatePacks(ctx: MonorepoContext, options?: ValidatePackOptions, hooks?: ValidatePackRunHooks): Promise<ValidatePackResult>;
31
+ export declare function resolvedTargetsByProject(projects: ProjectTargets[]): Map<string, ResolvedProjectTargets>;
29
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/monorepo/packs/index.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClD,WAAW,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACzD,YAAY,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,gBAAgB,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAClE,iBAAiB,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CACpE;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CAC9F;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AA4GD,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAItE;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,mBAAwB,EACjC,KAAK,GAAE,oBAAyB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CA0B7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/monorepo/packs/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,cAAc,EAAsB,MAAM,mBAAmB,CAAC;AAK5E,OAAO,EAKL,KAAK,sBAAsB,EAO5B,MAAM,sBAAsB,CAAC;AAU9B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClD,WAAW,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACzD,YAAY,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,gBAAgB,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAClE,iBAAiB,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CACpE;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CAC9F;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAqHD,wBAAsB,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAItE;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,mBAAwB,EACjC,KAAK,GAAE,oBAAyB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CA0B7B;AAuMD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAaxG"}
@@ -3,12 +3,12 @@ import { join } from 'node:path';
3
3
  import { printCommandOutput, runResult, runStatus } from '../../lib/run.js';
4
4
  import { readProjectTargets } from '../../nx/index.js';
5
5
  import { syncBunLockfileVersions, validateBunLockfileVersions } from '../lockfile.js';
6
- import { validateManagedFiles } from '../managed-files.js';
6
+ import { warnOnManagedFileDrift } from '../managed-files.js';
7
7
  import { fixNxSync, validateNxSync } from '../nx-sync.js';
8
8
  import { fixPackageHygiene, validatePackageHygiene } from '../package-hygiene.js';
9
9
  import { applyFixableMonorepoDefaults, applyNxReleaseDefaults, applyPublicPackageDefaults, applyWorkspaceDependencyDefaults, validateNxProjectNames, validateNxReleaseConfig, validatePublicPackageMetadata, validatePublicTags, validateRootPackagePolicy, validateWorkspaceDependencies, } from '../package-policy.js';
10
10
  import { validatePackedPublicPackageManifest, validatePackedPublicPackagePublint, validatePackedPublicPackageTypes, } from '../packed-package.js';
11
- import { syncRootRuntimeVersions } from '../runtime.js';
11
+ import { syncRootRuntimeVersions, validateRootRuntimeVersions } from '../runtime.js';
12
12
  import { applyToolConfigDefaults, validateToolConfig } from '../tool-validation.js';
13
13
  import { applyWranglerDefaults, validateWrangler } from '../wrangler.js';
14
14
  const packs = [
@@ -27,12 +27,21 @@ const packs = [
27
27
  async fixPreBuild(ctx) {
28
28
  applyFixableMonorepoDefaults(ctx.root);
29
29
  await applyToolConfigDefaults(ctx.root);
30
- syncBunLockfileVersions(ctx.root);
30
+ // Install/CI alignment only โ€” do not rewrite -next to stable tags here.
31
+ syncBunLockfileVersions(ctx.root, { mode: 'install' });
31
32
  await fixNxSync(ctx.root, ctx.verbose === true);
32
33
  applyWorkspaceDependencyDefaults(ctx.root, { resolvedTargetsByProject: await readResolvedTargetsByProject(ctx) });
33
34
  },
34
35
  async validatePreBuild(ctx) {
35
- return (validateManagedFiles(ctx.root) +
36
+ // Runtime pins validate against the live PATH runtimes (devenv shell),
37
+ // never a stored template โ€” outside devenv the PATH is not authoritative,
38
+ // mirroring the init-time syncRuntime gate above.
39
+ const runtimeFailures = ctx.syncRuntime ? await validateRootRuntimeVersions(ctx.root) : 0;
40
+ // Managed-file drift is derived state (CLI template x pinned version) with
41
+ // its own remediation flow; it warns instead of failing so validation only
42
+ // blocks on actual package issues. See warnOnManagedFileDrift.
43
+ warnOnManagedFileDrift(ctx.root);
44
+ return (runtimeFailures +
36
45
  validateRootPackagePolicy(ctx.root) +
37
46
  validateToolConfig(ctx.root) +
38
47
  validateNxProjectNames(ctx.root) +
@@ -302,18 +311,21 @@ function printCapturedOutput(output) {
302
311
  console.log(line);
303
312
  }
304
313
  }
305
- async function readResolvedTargetsByProject(ctx) {
306
- const projects = await readProjectTargets(ctx.root);
314
+ export function resolvedTargetsByProject(projects) {
307
315
  return new Map(projects.map((project) => [
308
316
  project.project,
309
317
  {
310
318
  targets: new Set(project.targets),
311
319
  ...(project.buildDependsOn ? { buildDependsOn: project.buildDependsOn } : {}),
320
+ ...(project.targetDependencies ? { targetDependencies: project.targetDependencies } : {}),
312
321
  ...(project.targetExecutors ? { targetExecutors: project.targetExecutors } : {}),
313
322
  ...(project.targetScripts ? { targetScripts: project.targetScripts } : {}),
314
323
  },
315
324
  ]));
316
325
  }
326
+ async function readResolvedTargetsByProject(ctx) {
327
+ return resolvedTargetsByProject(await readProjectTargets(ctx.root));
328
+ }
317
329
  function ensureLocalSmooShim(root) {
318
330
  const shim = join(root, 'tooling', 'smoo');
319
331
  if (!existsSync(shim)) {
@@ -34,6 +34,7 @@ export interface PublishWorkflowDefinitionOptions {
34
34
  deploy?: boolean;
35
35
  deployProvider?: 'cloudflare';
36
36
  repoName?: string;
37
+ platformTargetGlobs?: readonly string[];
37
38
  }
38
39
  export interface PublishWorkflowInputs {
39
40
  bump: PublishWorkflowBump;
@@ -1 +1 @@
1
- {"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"publish-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/publish-workflow.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,12 @@
1
1
  /* biome-ignore-all lint/suspicious/noTemplateCurlyInString: GitHub Actions expressions are emitted literally. */
2
+ import synchronizedPrettier from '@prettier/sync';
3
+ import { LINUX_PLATFORM_TARGET_GLOBS, MACOS_PLATFORM_TARGET_GLOBS, } from '@smoothbricks/nx-plugin/workspace-config-policy';
2
4
  import { isSmoothBricksCodebasePackageName } from '../lib/cli-package.js';
5
+ const PUBLISH_WORKFLOW_FORMAT_OPTIONS = Object.freeze({
6
+ parser: 'yaml',
7
+ printWidth: 120,
8
+ proseWrap: 'always',
9
+ });
3
10
  export var PublishWorkflowStepKind;
4
11
  (function (PublishWorkflowStepKind) {
5
12
  PublishWorkflowStepKind["Checkout"] = "checkout";
@@ -175,8 +182,18 @@ function shouldRunStep(step, version, failed, inputs) {
175
182
  return true;
176
183
  }
177
184
  export function renderPublishWorkflowYaml(options = {}) {
178
- const steps = definePublishWorkflow(options).steps;
179
- return `${renderPublishWorkflowHeader(options)}${renderPublishWorkflowSteps(steps, options)}`;
185
+ let workflow;
186
+ if (hasMacosPlatformTargets(options)) {
187
+ workflow = renderPlatformPublishWorkflowYaml(options);
188
+ }
189
+ else if (hasLinuxPlatformTargets(options)) {
190
+ workflow = `${renderPublishWorkflowHeader(options)}${renderSingleJobPublishWorkflowSteps(definePublishWorkflow(options).steps, options)}`;
191
+ }
192
+ else {
193
+ const steps = definePublishWorkflow(options).steps;
194
+ workflow = `${renderPublishWorkflowHeader(options)}${renderPublishWorkflowSteps(steps, options)}`;
195
+ }
196
+ return synchronizedPrettier.format(workflow, PUBLISH_WORKFLOW_FORMAT_OPTIONS);
180
197
  }
181
198
  function renderPublishWorkflowHeader(options) {
182
199
  const deployInput = options.deploy === true
@@ -309,7 +326,9 @@ function yamlLinesForStep(step, options) {
309
326
  ' "$GITHUB_OUTPUT"',
310
327
  ];
311
328
  case PublishWorkflowStepKind.CheckManagedMonorepoFiles:
312
- return conditionalRunStep(step, 'smoo monorepo check');
329
+ // Drift is derived state with its own remediation PR; publishing only
330
+ // blocks on actual package issues (smoo monorepo validate).
331
+ return conditionalRunStep(step, 'smoo monorepo check --warn');
313
332
  case PublishWorkflowStepKind.Build:
314
333
  return conditionalRunStep(step, `smoo github-ci nx-run-many --targets build --projects "${githubExpression('steps.version.outputs.projects')}"`);
315
334
  case PublishWorkflowStepKind.Lint:
@@ -375,6 +394,226 @@ function conditionalRunStep(step, run) {
375
394
  const condition = "steps.version.outputs.mode != 'none'";
376
395
  return [` - name: ${step.name}`, ` if: ${githubExpression(condition)}`, ` run: ${run}`];
377
396
  }
397
+ function renderSingleJobPublishWorkflowSteps(steps, options) {
398
+ const lines = [];
399
+ for (const step of steps) {
400
+ lines.push(...sectionLinesBefore(step));
401
+ lines.push(...commentLinesForStep(step));
402
+ lines.push(...yamlLinesForStep(step, options));
403
+ lines.push('');
404
+ if (step.kind === PublishWorkflowStepKind.Build) {
405
+ lines.push(' - name: ๐Ÿง Build supplemental Linux targets', ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ` run: smoo github-ci nx-run-many --targets "${LINUX_PLATFORM_TARGET_GLOBS.join(',')}" --projects "${githubExpression('steps.version.outputs.projects')}"`, '');
406
+ }
407
+ }
408
+ return `${lines.join('\n').trimEnd()}\n`;
409
+ }
410
+ function renderPlatformPublishWorkflowYaml(options) {
411
+ const deployInput = options.deploy === true
412
+ ? `
413
+ deploy_environment:
414
+ type: choice
415
+ description: Deploy live systems after a successful publish.
416
+ options: [none, production]
417
+ default: none`
418
+ : '';
419
+ const steps = definePublishWorkflow(options).steps;
420
+ return `name: Publish
421
+
422
+ on:
423
+ workflow_dispatch:
424
+ inputs:
425
+ bump:
426
+ type: choice
427
+ description:
428
+ Use auto for conventional commits, or force a semver bump. Prerelease publishes to next; all others publish to
429
+ latest.
430
+ options: [auto, patch, minor, major, prerelease]
431
+ default: auto
432
+ dry_run:
433
+ type: boolean
434
+ description: Run release commands without writing versions, tags, publishes, or GitHub Releases.
435
+ default: false${deployInput}
436
+
437
+ permissions:
438
+ contents: read
439
+
440
+ concurrency:
441
+ group: release-${githubExpression('github.ref')}
442
+ cancel-in-progress: false
443
+
444
+ defaults:
445
+ run:
446
+ working-directory: tooling/direnv
447
+
448
+ jobs:
449
+ linux-release-candidate:
450
+ runs-on: ubuntu-latest
451
+ permissions:
452
+ contents: write
453
+ id-token: none
454
+ outputs:
455
+ mode: ${githubExpression('steps.version.outputs.mode')}
456
+ release-sha: ${githubExpression('steps.release-state.outputs.sha')}
457
+ env:
458
+ NIX_STORE_NAR: ${githubExpression('github.workspace')}/nix-store.nar
459
+ GH_TOKEN: ${githubExpression('github.token')}
460
+ steps:
461
+ ${renderLinuxReleaseCandidateSteps(steps, options)}
462
+
463
+ macos-platform:
464
+ runs-on: macos-latest
465
+ permissions:
466
+ contents: read
467
+ id-token: none
468
+ env:
469
+ NIX_STORE_NAR: ${githubExpression('github.workspace')}/nix-store.nar
470
+ GH_TOKEN: ${githubExpression('github.token')}
471
+ steps:
472
+ ${renderMacosPlatformSteps(options)}
473
+
474
+ publish-on-linux:
475
+ needs: [linux-release-candidate, macos-platform]
476
+ runs-on: ubuntu-latest
477
+ permissions:
478
+ contents: write
479
+ id-token: write
480
+ env:
481
+ NIX_STORE_NAR: ${githubExpression('github.workspace')}/nix-store.nar
482
+ GH_TOKEN: ${githubExpression('github.token')}
483
+ steps:
484
+ ${renderFinalLinuxPublishSteps(options)}
485
+ `;
486
+ }
487
+ function renderLinuxReleaseCandidateSteps(steps, options) {
488
+ const lines = [];
489
+ let stepNumber = 2;
490
+ for (const step of steps) {
491
+ if (step.kind === PublishWorkflowStepKind.RepairPendingReleases ||
492
+ step.kind === PublishWorkflowStepKind.PublishRelease ||
493
+ step.kind === PublishWorkflowStepKind.DeployProduction ||
494
+ step.kind === PublishWorkflowStepKind.SaveNixDevenv) {
495
+ continue;
496
+ }
497
+ lines.push(...sectionLinesBefore(step));
498
+ if (step.kind === PublishWorkflowStepKind.Checkout) {
499
+ lines.push(' # Step 1: GitHub adds "Set up job" automatically', ` # Step ${stepNumber}`);
500
+ }
501
+ else if (step.kind === PublishWorkflowStepKind.SetupDevenv) {
502
+ lines.push(` # Step ${stepNumber}. Composite action internals do not affect top-level job step`, ' # anchors; update these comments if top-level steps move.');
503
+ }
504
+ else {
505
+ lines.push(` # Step ${stepNumber}`);
506
+ }
507
+ if (step.kind === PublishWorkflowStepKind.Checkout) {
508
+ lines.push(` - name: ${step.name}`, ' uses: actions/checkout@v6.0.2', ' with:', ` ref: ${githubExpression('github.sha')}`, ' filter: blob:none', ' fetch-depth: 0');
509
+ }
510
+ else if (step.kind === PublishWorkflowStepKind.Build) {
511
+ lines.push(` - name: ${step.name}`, ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ' run:', ` smoo github-ci nx-run-many --targets build --projects "${githubExpression('steps.version.outputs.projects')}" --collect-outputs "${githubExpression('runner.temp')}/release-build-outputs"`);
512
+ }
513
+ else {
514
+ lines.push(...yamlLinesForStep(step, options));
515
+ }
516
+ stepNumber += 1;
517
+ if (step.kind === PublishWorkflowStepKind.VersionRelease) {
518
+ lines.push('', ` # Step ${stepNumber}`, ' - name: ๐Ÿ”’ Capture candidate release SHA', ' id: release-state', ' run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"');
519
+ stepNumber += 1;
520
+ }
521
+ if (step.kind === PublishWorkflowStepKind.Build && hasLinuxPlatformTargets(options)) {
522
+ lines.push('', ` # Step ${stepNumber}`, ' - name: ๐Ÿง Build supplemental Linux targets', ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ' run:', ` smoo github-ci nx-run-many --targets "${LINUX_PLATFORM_TARGET_GLOBS.join(',')}" --projects "${githubExpression('steps.version.outputs.projects')}" --collect-outputs "${githubExpression('runner.temp')}/linux-platform-outputs"`);
523
+ stepNumber += 1;
524
+ }
525
+ lines.push('');
526
+ }
527
+ lines.push(' # --- Candidate transfer --------------------------------------------------', '', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ“ฆ Bundle validated release state', ' run:', ` mkdir -p "${githubExpression('runner.temp')}/publish-release-state" && git bundle create`, ` "${githubExpression('runner.temp')}/publish-release-state/release-state.bundle" HEAD --tags && git rev-parse HEAD >`, ` "${githubExpression('runner.temp')}/publish-release-state/release-head"`, '', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ“ค Upload validated release state', ' uses: actions/upload-artifact@v7.0.1', ' with:', ` name: publish-release-state-${githubExpression('github.run_id')}`, ` path: ${githubExpression('runner.temp')}/publish-release-state`, ' if-no-files-found: error', ' retention-days: 1', '', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ“ค Upload validated build outputs', ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ' uses: actions/upload-artifact@v7.0.1', ' with:', ` name: publish-release-outputs-${githubExpression('github.run_id')}`, ` path: ${githubExpression('runner.temp')}/release-build-outputs`, ' if-no-files-found: error', ' retention-days: 1', ' include-hidden-files: true');
528
+ if (hasLinuxPlatformTargets(options)) {
529
+ lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ“ค Upload supplemental Linux outputs', ` if: ${githubExpression("steps.version.outputs.mode != 'none'")}`, ' uses: actions/upload-artifact@v7.0.1', ' with:', ` name: publish-linux-outputs-${githubExpression('github.run_id')}`, ` path: ${githubExpression('runner.temp')}/linux-platform-outputs`, ' if-no-files-found: error', ' retention-days: 1', ' include-hidden-files: true');
530
+ }
531
+ lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐Ÿงน Cleanup and cache Nix/devenv', ` if: ${githubExpression('always()')}`, ' uses: ./.github/actions/save-nix-devenv', ' with:', ` nix-cache-hit: ${githubExpression('steps.setup.outputs.nix-cache-hit')}`, ` devenv-cache-hit: ${githubExpression('steps.setup.outputs.devenv-cache-hit')}`);
532
+ return lines.join('\n').trimEnd();
533
+ }
534
+ function renderMacosPlatformSteps(options) {
535
+ let stepNumber = 4;
536
+ const lines = [
537
+ ' # --- Setup --------------------------------------------------------------',
538
+ '',
539
+ ' # Step 1: GitHub adds "Set up job" automatically',
540
+ ' # Step 2',
541
+ ' - name: ๐Ÿ“ฅ Checkout dispatch commit',
542
+ ' uses: actions/checkout@v6.0.2',
543
+ ' with:',
544
+ ` ref: ${githubExpression('github.sha')}`,
545
+ ' filter: blob:none',
546
+ ' fetch-depth: 0',
547
+ '',
548
+ ' # Step 3. Composite action internals do not affect top-level job step',
549
+ ' # anchors; update these comments if top-level steps move.',
550
+ ' - name: ๐Ÿงฑ Setup Nix/devenv',
551
+ ' id: setup',
552
+ ' uses: ./.github/actions/setup-devenv',
553
+ ];
554
+ if (isSmoothBricksCodebasePackageName(options.repoName)) {
555
+ lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ—๏ธ Build self-hosted smoo', ' # SmoothBricks self-hosts smoo from source for release commands.', ' run: nx build cli');
556
+ }
557
+ lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ŸŽ Build selected macOS and iOS release outputs', ' run:', ` smoo release build-platform-outputs --bump "${githubExpression('inputs.bump')}" --ref "${githubExpression('github.sha')}" --targets "${MACOS_PLATFORM_TARGET_GLOBS.join(',')}" --output`, ` "${githubExpression('runner.temp')}/macos-platform-outputs"`, '', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ“ค Upload macOS platform outputs', ' uses: actions/upload-artifact@v7.0.1', ' with:', ` name: publish-macos-outputs-${githubExpression('github.run_id')}`, ` path: ${githubExpression('runner.temp')}/macos-platform-outputs`, ' if-no-files-found: error', ' retention-days: 1', ' include-hidden-files: true', '', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐Ÿงน Cleanup and cache Nix/devenv', ` if: ${githubExpression('always()')}`, ' uses: ./.github/actions/save-nix-devenv', ' with:', ` nix-cache-hit: ${githubExpression('steps.setup.outputs.nix-cache-hit')}`, ` devenv-cache-hit: ${githubExpression('steps.setup.outputs.devenv-cache-hit')}`);
558
+ return lines.join('\n').trimEnd();
559
+ }
560
+ function renderFinalLinuxPublishSteps(options) {
561
+ const mode = 'needs.linux-release-candidate.outputs.mode';
562
+ let stepNumber = 2;
563
+ const lines = [
564
+ ' # --- Setup --------------------------------------------------------------',
565
+ '',
566
+ ' # Step 1: GitHub adds "Set up job" automatically',
567
+ ` # Step ${stepNumber++}`,
568
+ ' - name: ๐Ÿ“ฅ Checkout dispatch commit',
569
+ ' uses: actions/checkout@v6.0.2',
570
+ ' with:',
571
+ ` ref: ${githubExpression('github.sha')}`,
572
+ ' filter: blob:none',
573
+ ' fetch-depth: 0',
574
+ '',
575
+ ` # Step ${stepNumber++}`,
576
+ ' - name: ๐Ÿ“ฅ Download candidate artifacts',
577
+ ' uses: actions/download-artifact@v8.0.1',
578
+ ' with:',
579
+ ` pattern: publish-*-${githubExpression('github.run_id')}`,
580
+ ` path: ${githubExpression('runner.temp')}/publish-artifacts`,
581
+ ' merge-multiple: false',
582
+ '',
583
+ ` # Step ${stepNumber}. Composite action internals do not affect top-level job step`,
584
+ ' # anchors; update these comments if top-level steps move.',
585
+ ' - name: ๐Ÿงฑ Setup Nix/devenv',
586
+ ' id: setup',
587
+ ' uses: ./.github/actions/setup-devenv',
588
+ '',
589
+ ` # Step ${++stepNumber}`,
590
+ ' - name: ๐Ÿค– Configure release author',
591
+ ' run:',
592
+ ' git config user.name "github-actions[bot]" && git config user.email',
593
+ ' "41898282+github-actions[bot]@users.noreply.github.com"',
594
+ ];
595
+ stepNumber += 1;
596
+ if (isSmoothBricksCodebasePackageName(options.repoName)) {
597
+ lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ—๏ธ Build self-hosted smoo', ' # SmoothBricks self-hosts smoo from source for release commands.', ' run: nx build cli');
598
+ }
599
+ lines.push('', ' # --- Repair -------------------------------------------------------------', '', ` # Step ${stepNumber++}`, ' - name: ๐Ÿงฏ Repair pending releases', ' run:', ` smoo release repair-pending --ref "${githubExpression('github.sha')}" --platform-outputs "${githubExpression('runner.temp')}/publish-artifacts/publish-macos-outputs-${githubExpression('github.run_id')}/repairs" --dry-run`, ` "${githubExpression('inputs.dry_run')}"`, '', ` # Step ${stepNumber++}`, ' - name: โ™ป๏ธ Restore validated release state', ' run:', ` git fetch "${githubExpression('runner.temp')}/publish-artifacts/publish-release-state-${githubExpression('github.run_id')}/release-state.bundle" HEAD --tags && git reset`, ` --hard "$(cat "${githubExpression('runner.temp')}/publish-artifacts/publish-release-state-${githubExpression('github.run_id')}/release-head")"`);
600
+ lines.push('', ' # --- Validation ---------------------------------------------------------', '', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ“ฆ Apply verified Linux outputs', ` if: ${githubExpression(`${mode} != 'none'`)}`, ' run:', ` smoo github-ci apply-outputs --source-sha "${githubExpression('needs.linux-release-candidate.outputs.release-sha')}"`, ` "${githubExpression('runner.temp')}/publish-artifacts/publish-release-outputs-${githubExpression('github.run_id')}"`);
601
+ if (hasLinuxPlatformTargets(options)) {
602
+ lines.push(` "${githubExpression('runner.temp')}/publish-artifacts/publish-linux-outputs-${githubExpression('github.run_id')}"`);
603
+ }
604
+ lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ŸŽ Apply verified macOS outputs', ` if: ${githubExpression(`${mode} != 'none'`)}`, ' run:', ` smoo github-ci apply-outputs --source-sha "${githubExpression('github.sha')}"`, ` "${githubExpression('runner.temp')}/publish-artifacts/publish-macos-outputs-${githubExpression('github.run_id')}/current"`, '', ` # Step ${stepNumber++}`, ` - name: โœ… Validate restored release (${githubExpression(mode)})`, ` if: ${githubExpression(`${mode} != 'none'`)}`, ' run: smoo monorepo validate', '', ' # --- Release ------------------------------------------------------------', '', ` # Step ${stepNumber++}`, ` - name: ๐Ÿ“ฆ Publish release (${githubExpression(mode)})`, ' # smoo packs with Bun, then publishes tarballs with npm. Existing', ' # packages must already exist on npm and use trusted publishing/OIDC.', ' # Missing package names are bootstrapped locally before trust setup.', ` run: smoo release publish --bump "${githubExpression('inputs.bump')}" --dry-run "${githubExpression('inputs.dry_run')}"`);
605
+ if (options.deploy === true) {
606
+ lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐Ÿš€ Deploy production', ' if:', " ${{ needs.linux-release-candidate.outputs.mode != 'none' && inputs.deploy_environment == 'production' &&", " inputs.dry_run != 'true' }}", ...deployEnvLines(options), ' run: smoo github-ci nx-deploy --configuration production --mode run-many --verify --name "Deploy Production"');
607
+ }
608
+ lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐Ÿงน Cleanup and cache Nix/devenv', ` if: ${githubExpression('always()')}`, ' uses: ./.github/actions/save-nix-devenv', ' with:', ` nix-cache-hit: ${githubExpression('steps.setup.outputs.nix-cache-hit')}`, ` devenv-cache-hit: ${githubExpression('steps.setup.outputs.devenv-cache-hit')}`);
609
+ return lines.join('\n').trimEnd();
610
+ }
611
+ function hasMacosPlatformTargets(options) {
612
+ return MACOS_PLATFORM_TARGET_GLOBS.some((glob) => options.platformTargetGlobs?.includes(glob) === true);
613
+ }
614
+ function hasLinuxPlatformTargets(options) {
615
+ return LINUX_PLATFORM_TARGET_GLOBS.some((glob) => options.platformTargetGlobs?.includes(glob) === true);
616
+ }
378
617
  function githubExpression(expression) {
379
618
  return ['$', '{{ ', expression, ' }}'].join('');
380
619
  }
@@ -1,4 +1,19 @@
1
+ import { type PackageJson } from '../lib/json.js';
2
+ export interface RuntimeVersions {
3
+ node: string;
4
+ bun: string;
5
+ }
6
+ /** Live runtime versions from the shell PATH โ€” the single source sync AND validate derive from. */
7
+ export declare function runtimeVersionsFromPath(root: string): Promise<RuntimeVersions>;
1
8
  export declare function syncRootRuntimeVersions(root: string): Promise<void>;
9
+ /**
10
+ * Validate that package.json runtime pins agree with the LIVE PATH runtimes,
11
+ * never a stored template. Offline by design: structural alignment only
12
+ * (majors, exact bun pin, no `~major.0.0` floor) โ€” the registry is not
13
+ * consulted. Repair: `smoo monorepo init --runtime-only` inside the devenv shell.
14
+ */
15
+ export declare function validateRootRuntimeVersions(root: string): Promise<number>;
16
+ export declare function validateRuntimePins(packageJson: PackageJson, runtime: RuntimeVersions): number;
2
17
  type RuntimeTypesPinMode = 'major' | 'exact';
3
18
  export declare function runtimeTypesRangeForPublishedVersions(packageName: string, runtimeVersion: string, pinMode: RuntimeTypesPinMode, versions: readonly string[]): string;
4
19
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/monorepo/runtime.ts"],"names":[],"mappings":"AAKA,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCzE;AAED,KAAK,mBAAmB,GAAG,OAAO,GAAG,OAAO,CAAC;AAgB7C,wBAAgB,qCAAqC,CACnD,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,MAAM,CAsBR"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/monorepo/runtime.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,WAAW,EAMjB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,mGAAmG;AACnG,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAOpF;AAED,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCzE;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO/E;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CAmC9F;AAED,KAAK,mBAAmB,GAAG,OAAO,GAAG,OAAO,CAAC;AAgB7C,wBAAgB,qCAAqC,CACnD,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,MAAM,CA2BR"}