@smoothbricks/cli 0.10.6 โ†’ 0.10.8

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 (82) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +24 -1
  3. package/dist/github-ci/index.d.ts +44 -3
  4. package/dist/github-ci/index.d.ts.map +1 -1
  5. package/dist/github-ci/index.js +242 -36
  6. package/dist/lib/json.d.ts +1 -1
  7. package/dist/lib/json.d.ts.map +1 -1
  8. package/dist/lib/json.js +3 -18
  9. package/dist/lib/workspace.d.ts.map +1 -1
  10. package/dist/lib/workspace.js +1 -0
  11. package/dist/monorepo/ci-workflow.js +16 -6
  12. package/dist/monorepo/managed-files.d.ts +6 -22
  13. package/dist/monorepo/managed-files.d.ts.map +1 -1
  14. package/dist/monorepo/managed-files.js +31 -48
  15. package/dist/monorepo/package-policy.js +2 -2
  16. package/dist/monorepo/packs/index.d.ts.map +1 -1
  17. package/dist/monorepo/packs/index.js +2 -0
  18. package/dist/monorepo/pr-preview-cleanup-workflow.d.ts +5 -0
  19. package/dist/monorepo/pr-preview-cleanup-workflow.d.ts.map +1 -0
  20. package/dist/monorepo/pr-preview-cleanup-workflow.js +38 -0
  21. package/dist/monorepo/publish-workflow.js +3 -3
  22. package/dist/monorepo/runtime.d.ts +2 -2
  23. package/dist/monorepo/runtime.d.ts.map +1 -1
  24. package/dist/monorepo/runtime.js +11 -16
  25. package/dist/monorepo/tool-validation.d.ts.map +1 -1
  26. package/dist/monorepo/tool-validation.js +105 -28
  27. package/dist/nx/index.d.ts +7 -4
  28. package/dist/nx/index.d.ts.map +1 -1
  29. package/dist/nx/index.js +117 -56
  30. package/dist/playwright/index.d.ts +22 -0
  31. package/dist/playwright/index.d.ts.map +1 -0
  32. package/dist/playwright/index.js +44 -0
  33. package/dist/release/bootstrap-npm-packages.d.ts +3 -0
  34. package/dist/release/bootstrap-npm-packages.d.ts.map +1 -1
  35. package/dist/release/bootstrap-npm-packages.js +21 -0
  36. package/dist/release/index.d.ts.map +1 -1
  37. package/dist/release/index.js +17 -0
  38. package/dist/wrangler/cloudflare.d.ts +85 -0
  39. package/dist/wrangler/cloudflare.d.ts.map +1 -0
  40. package/dist/wrangler/cloudflare.js +235 -0
  41. package/dist/wrangler/deploy-environment.d.ts +48 -0
  42. package/dist/wrangler/deploy-environment.d.ts.map +1 -0
  43. package/dist/wrangler/deploy-environment.js +383 -0
  44. package/dist/wrangler/environment.d.ts +58 -0
  45. package/dist/wrangler/environment.d.ts.map +1 -0
  46. package/dist/wrangler/environment.js +297 -0
  47. package/managed/raw/tooling/devenv +71 -0
  48. package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +3 -4
  49. package/package.json +11 -4
  50. package/src/cli.ts +33 -3
  51. package/src/github-ci/index.test.ts +221 -1
  52. package/src/github-ci/index.ts +303 -32
  53. package/src/lib/json.ts +1 -1
  54. package/src/lib/workspace.ts +1 -0
  55. package/src/monorepo/__tests__/ci-workflow.test.ts +10 -4
  56. package/src/monorepo/__tests__/pr-preview-cleanup-workflow.test.ts +23 -0
  57. package/src/monorepo/__tests__/publish-workflow.test.ts +12 -4
  58. package/src/monorepo/ci-workflow.ts +16 -6
  59. package/src/monorepo/managed-files.test.ts +87 -23
  60. package/src/monorepo/managed-files.ts +35 -69
  61. package/src/monorepo/package-policy.test.ts +31 -0
  62. package/src/monorepo/package-policy.ts +2 -2
  63. package/src/monorepo/packs/index.ts +2 -0
  64. package/src/monorepo/pr-preview-cleanup-workflow.ts +44 -0
  65. package/src/monorepo/publish-workflow.ts +7 -2
  66. package/src/monorepo/runtime.test.ts +23 -17
  67. package/src/monorepo/runtime.ts +12 -17
  68. package/src/monorepo/tool-validation.test.ts +100 -8
  69. package/src/monorepo/tool-validation.ts +115 -31
  70. package/src/nx/index.test.ts +45 -14
  71. package/src/nx/index.ts +133 -64
  72. package/src/playwright/index.test.ts +90 -0
  73. package/src/playwright/index.ts +73 -0
  74. package/src/release/__tests__/bootstrap-npm-packages.test.ts +63 -2
  75. package/src/release/bootstrap-npm-packages.ts +34 -0
  76. package/src/release/index.ts +18 -0
  77. package/src/wrangler/cloudflare.ts +289 -0
  78. package/src/wrangler/deploy-environment.test.ts +354 -0
  79. package/src/wrangler/deploy-environment.ts +445 -0
  80. package/src/wrangler/environment.test.ts +173 -0
  81. package/src/wrangler/environment.ts +366 -0
  82. package/managed/raw/patches/ttsc@0.19.3.patch +0 -67
@@ -29,7 +29,7 @@ export function defineCiWorkflow(options) {
29
29
  { kind: CiWorkflowStepKind.ManagedFilesDispatch, name: '๐Ÿ” Dispatch managed-file drift healing' },
30
30
  ];
31
31
  if (options.deploy) {
32
- steps.push({ kind: CiWorkflowStepKind.Deploy, name: '๐Ÿš€ Deploy Staging' });
32
+ steps.push({ kind: CiWorkflowStepKind.Deploy, name: '๐Ÿš€ Deploy Environment' });
33
33
  }
34
34
  steps.push({ kind: CiWorkflowStepKind.SaveNxCache, name: '๐Ÿ’พ Save Nx cache' }, { kind: CiWorkflowStepKind.UploadTraceDbs, name: '๐Ÿ“Ž Upload trace DBs' }, { kind: CiWorkflowStepKind.SaveNixDevenv, name: '๐Ÿงน Cleanup and cache Nix/devenv' });
35
35
  return steps.map((step, index) => ({ ...step, number: index + 2 }));
@@ -51,7 +51,7 @@ permissions:
51
51
  # actions:write lets the drift step dispatch the managed-files workflow.
52
52
  actions: write
53
53
  contents: read
54
- statuses: write
54
+ ${options.deploy ? ' deployments: write\n' : ''} statuses: write
55
55
 
56
56
  defaults:
57
57
  run:
@@ -167,11 +167,15 @@ function yamlLinesForStep(step, options) {
167
167
  case CiWorkflowStepKind.Deploy:
168
168
  return [
169
169
  ` - name: ${step.name}`,
170
- ' if:',
171
- " ${{ github.event_name == 'push' && github.ref == format('refs/heads/{0}',",
172
- ' github.event.repository.default_branch) }}',
170
+ ' if: >-',
171
+ ' ${{',
172
+ " (github.event_name == 'pull_request' &&",
173
+ ' contains(fromJSON(\'["opened","reopened","synchronize"]\'), github.event.action) &&',
174
+ ' github.event.pull_request.head.repo.full_name == github.repository) ||',
175
+ " (github.event_name == 'push' && github.ref == 'refs/heads/private')",
176
+ ' }}',
173
177
  ...deployEnvLines(options),
174
- ` run: smoo github-ci nx-deploy --configuration staging --mode affected --name "Deploy Staging" --step ${step.number}`,
178
+ ` run: smoo github-ci nx-deploy --mode run-many --name "Deploy Environment" --step ${step.number}`,
175
179
  ];
176
180
  case CiWorkflowStepKind.SaveNxCache:
177
181
  return [
@@ -220,6 +224,12 @@ function deployEnvLines(options) {
220
224
  ' env:',
221
225
  ' CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}',
222
226
  ' CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}',
227
+ ' GITHUB_CLIENT_SECRET: ${{ secrets.GITHUB_CLIENT_SECRET }}',
228
+ ' GITHUB_APP_PRIVATE_KEY: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}',
229
+ ' GITHUB_APP_PRIVATE_KEY_PEM: ${{ secrets.GITHUB_APP_PRIVATE_KEY_PEM }}',
230
+ ' OAUTH_STATE_SIGNING_KEY: ${{ secrets.OAUTH_STATE_SIGNING_KEY }}',
231
+ ' MAIL_CAPTURE_CONTROL_TOKEN: ${{ secrets.MAIL_CAPTURE_CONTROL_TOKEN }}',
232
+ ' TOKEN_ENCRYPTION_KEY: ${{ secrets.TOKEN_ENCRYPTION_KEY }}',
223
233
  ];
224
234
  }
225
235
  function nxSmartStep(step, target, name) {
@@ -1,3 +1,4 @@
1
+ import { type NxProjects } from '../nx/index.js';
1
2
  /**
2
3
  * Repos may append their own content to a managed file below this marker โ€”
3
4
  * e.g. extra merge drivers in .gitattributes. Everything from the marker
@@ -51,31 +52,14 @@ interface DeployTargetInfo {
51
52
  exists: boolean;
52
53
  provider?: 'cloudflare';
53
54
  }
55
+ export declare const managedFileTargetsForTest: {
56
+ target: string;
57
+ executable: boolean | undefined;
58
+ }[];
54
59
  export declare function applyManagedFiles(root: string, mode: 'update' | 'check' | 'diff'): Promise<FileResult[]>;
55
60
  export declare function platformTargetGlobsForTest(targetNames: Iterable<string>): string[];
56
- /** Resolved Nx project node as returned under `graph.nodes` / project-graph.json. */
57
- export type NxGraphProjectNode = {
58
- data?: {
59
- targets?: Record<string, NxGraphTarget>;
60
- };
61
- targets?: Record<string, NxGraphTarget>;
62
- };
63
- type NxGraphTarget = {
64
- command?: string;
65
- options?: {
66
- command?: string;
67
- };
68
- configurations?: Record<string, {
69
- command?: string;
70
- options?: {
71
- command?: string;
72
- };
73
- }>;
74
- };
75
- /** Test seam: collect target names from a graph.nodes map. */
76
- export declare function targetNamesFromProjects(nodes: Record<string, NxGraphProjectNode>): string[];
77
61
  /** Test seam: deploy configuration presence/provider from graph nodes. */
78
- export declare function deployTargetInfoFromProjects(nodes: Record<string, NxGraphProjectNode>, configuration: string): DeployTargetInfo;
62
+ export declare function deployTargetInfoFromProjects(projects: NxProjects, configuration: string): DeployTargetInfo;
79
63
  export declare function printResults(results: FileResult[]): void;
80
64
  export declare function validateManagedFiles(root: string): Promise<number>;
81
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"AAMA,OAAO,EAAkB,KAAK,UAAU,EAA2B,MAAM,gBAAgB,CAAC;AAO1F;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,yEAAyE,CAAC;AAW3G,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;AAeD,UAAU,gBAAgB;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAkHD,eAAO,MAAM,yBAAyB;;;GAAyE,CAAC;AAIhH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAG9G;AAyGD,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAMlF;AAED,0EAA0E;AAC1E,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,GAAG,gBAAgB,CAY1G;AA2DD,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAIxD;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQxE;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBxE"}
@@ -2,10 +2,10 @@ import { appendFileSync, existsSync, lstatSync, mkdirSync, readFileSync, writeFi
2
2
  import { dirname, join, resolve } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { PLATFORM_TARGET_GLOBS } from '@smoothbricks/nx-plugin/workspace-config-policy';
5
- // Nx package exports are CLI-oriented; this is the module the CLI uses for graph + daemon IPC.
6
- import { createProjectGraphAsync } from 'nx/src/project-graph/project-graph.js';
7
5
  import { listReleasePackages, readPackageJson } from '../lib/workspace.js';
6
+ import { loadNxProjects, targetNamesFromProjects } from '../nx/index.js';
8
7
  import { renderCiWorkflowYaml } from './ci-workflow.js';
8
+ import { renderPrPreviewCleanupWorkflowYaml } from './pr-preview-cleanup-workflow.js';
9
9
  import { renderPublishWorkflowYaml } from './publish-workflow.js';
10
10
  /**
11
11
  * Repos may append their own content to a managed file below this marker โ€”
@@ -100,6 +100,12 @@ const managedFiles = [
100
100
  source: 'envrc',
101
101
  target: '.envrc',
102
102
  },
103
+ {
104
+ kind: 'raw',
105
+ source: 'tooling/devenv',
106
+ target: 'tooling/devenv',
107
+ executable: true,
108
+ },
103
109
  {
104
110
  kind: 'raw',
105
111
  source: 'tooling/direnv/repo-path',
@@ -146,16 +152,17 @@ const managedFiles = [
146
152
  target: 'tooling/direnv/merge-newer-pins.sh',
147
153
  executable: true,
148
154
  },
149
- {
150
- kind: 'raw',
151
- source: 'patches/ttsc@0.19.3.patch',
152
- target: 'patches/ttsc@0.19.3.patch',
153
- },
154
155
  {
155
156
  kind: 'generated',
156
157
  source: 'ci-workflow',
157
158
  target: '.github/workflows/ci.yml',
158
159
  },
160
+ {
161
+ kind: 'generated',
162
+ source: 'pr-preview-cleanup-workflow',
163
+ target: '.github/workflows/pr-preview-cleanup.yml',
164
+ cloudflareDeployOnly: true,
165
+ },
159
166
  {
160
167
  kind: 'generated',
161
168
  source: 'publish-workflow',
@@ -198,6 +205,7 @@ const managedFiles = [
198
205
  target: '.github/actions/cache-nx/action.yml',
199
206
  },
200
207
  ];
208
+ export const managedFileTargetsForTest = managedFiles.map(({ target, executable }) => ({ target, executable }));
201
209
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
202
210
  export async function applyManagedFiles(root, mode) {
203
211
  const context = await getManagedFileContext(root);
@@ -207,6 +215,9 @@ function applyManagedFile(root, file, mode, context) {
207
215
  if (file.releasePackagesOnly === true && !context.hasReleasePackages && !context.hasProductionDeployTargets) {
208
216
  return { target: file.target, action: 'skipped' };
209
217
  }
218
+ if (file.cloudflareDeployOnly === true && context.stagingDeployProvider !== 'cloudflare') {
219
+ return { target: file.target, action: 'skipped' };
220
+ }
210
221
  const target = resolve(root, file.target);
211
222
  const content = getManagedContent(file, context);
212
223
  if (existsSync(target)) {
@@ -256,6 +267,9 @@ function getManagedContent(file, context) {
256
267
  runsOn: context.ciRunsOn,
257
268
  });
258
269
  }
270
+ if (file.source === 'pr-preview-cleanup-workflow') {
271
+ return renderPrPreviewCleanupWorkflowYaml({ runsOn: context.ciRunsOn });
272
+ }
259
273
  throw new Error(`Unknown generated managed file source ${file.source}`);
260
274
  }
261
275
  const sourceRoot = file.kind === 'raw' ? 'managed/raw' : 'managed/templates';
@@ -272,7 +286,7 @@ async function getManagedFileContext(root) {
272
286
  const ciPushBranches = getCiPushBranches(packageJson?.json);
273
287
  const ciRunsOn = getCiRunsOn(packageJson?.json);
274
288
  // In-process Nx API โ†’ daemon socket (no second Node/`nx` CLI process).
275
- const nxProjects = await loadNxGraphProjects(root);
289
+ const nxProjects = await loadNxProjects(root);
276
290
  const stagingDeploy = deployTargetInfoFromProjects(nxProjects, 'staging');
277
291
  const productionDeploy = deployTargetInfoFromProjects(nxProjects, 'production');
278
292
  const platformTargetGlobs = platformTargetGlobsForTest(targetNamesFromProjects(nxProjects));
@@ -299,48 +313,12 @@ export function platformTargetGlobsForTest(targetNames) {
299
313
  return names.some((name) => name.endsWith(suffix));
300
314
  });
301
315
  }
302
- /**
303
- * Load resolved project nodes via Nx's programmatic API.
304
- *
305
- * `createProjectGraphAsync` is what the CLI uses: with the daemon up it speaks the
306
- * daemon unix socket instead of rebuilding the graph in a fresh Node process.
307
- * Spawning `nx graph` / `nx show` only added CLI boot + plugin-worker overhead on
308
- * top of that. smoo runs under Bun; Bun can import this CJS module directly.
309
- */
310
- async function loadNxGraphProjects(root) {
311
- const prevCwd = process.cwd();
312
- process.chdir(root);
313
- try {
314
- const graph = (await createProjectGraphAsync());
315
- const out = {};
316
- for (const [name, node] of Object.entries(graph.nodes)) {
317
- out[name] = { data: { targets: node.data?.targets ?? {} } };
318
- }
319
- return out;
320
- }
321
- finally {
322
- process.chdir(prevCwd);
323
- }
324
- }
325
- function targetsOfProject(node) {
326
- return node.data?.targets ?? node.targets ?? {};
327
- }
328
- /** Test seam: collect target names from a graph.nodes map. */
329
- export function targetNamesFromProjects(nodes) {
330
- const targetNames = new Set();
331
- for (const node of Object.values(nodes)) {
332
- for (const name of Object.keys(targetsOfProject(node))) {
333
- targetNames.add(name);
334
- }
335
- }
336
- return [...targetNames];
337
- }
338
316
  /** Test seam: deploy configuration presence/provider from graph nodes. */
339
- export function deployTargetInfoFromProjects(nodes, configuration) {
317
+ export function deployTargetInfoFromProjects(projects, configuration) {
340
318
  let exists = false;
341
319
  let provider;
342
- for (const node of Object.values(nodes)) {
343
- const info = deployTargetInfoFromTargets(targetsOfProject(node), configuration);
320
+ for (const project of Object.values(projects)) {
321
+ const info = deployTargetInfoFromTargets(project.targets ?? {}, configuration);
344
322
  if (!info.exists) {
345
323
  continue;
346
324
  }
@@ -354,11 +332,16 @@ function deployTargetInfoFromTargets(targets, configuration) {
354
332
  if (!deploy) {
355
333
  return { exists: false };
356
334
  }
335
+ const baseCommandValue = deploy.options?.command ?? deploy.command;
336
+ const baseCommand = typeof baseCommandValue === 'string' ? baseCommandValue : '';
337
+ if (baseCommand.includes('smoo wrangler deploy-environment')) {
338
+ return { exists: true, provider: 'cloudflare' };
339
+ }
357
340
  const config = deploy.configurations?.[configuration];
358
341
  if (!config) {
359
342
  return { exists: false };
360
343
  }
361
- const commandValue = config.command ?? config.options?.command ?? deploy.options?.command ?? deploy.command;
344
+ const commandValue = config.command ?? config.options?.command ?? baseCommand;
362
345
  const command = typeof commandValue === 'string' ? commandValue : '';
363
346
  return { exists: true, provider: command.includes('wrangler ') ? 'cloudflare' : undefined };
364
347
  }
@@ -113,7 +113,7 @@ export function applyWorkspaceDependencyDefaults(root, options = {}) {
113
113
  else {
114
114
  console.log('unchanged tsconfig.test.json policy');
115
115
  }
116
- if (applyWorkspaceBoundedTestTargetPolicy(root)) {
116
+ if (applyWorkspaceBoundedTestTargetPolicy(root, options)) {
117
117
  console.log('updated package test targets bounded execution policy');
118
118
  }
119
119
  else {
@@ -343,7 +343,7 @@ export function validateWorkspaceDependencies(root, options = {}) {
343
343
  console.error(`${issue.path}: ${issue.message}`);
344
344
  failures++;
345
345
  }
346
- for (const issue of checkWorkspaceBoundedTestTargetPolicy(root)) {
346
+ for (const issue of checkWorkspaceBoundedTestTargetPolicy(root, options)) {
347
347
  console.error(`${issue.path}: ${issue.message}`);
348
348
  failures++;
349
349
  }
@@ -1 +1 @@
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"}
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,CAexG"}
@@ -315,10 +315,12 @@ export function resolvedTargetsByProject(projects) {
315
315
  return new Map(projects.map((project) => [
316
316
  project.project,
317
317
  {
318
+ ...(project.root ? { root: project.root } : {}),
318
319
  targets: new Set(project.targets),
319
320
  ...(project.buildDependsOn ? { buildDependsOn: project.buildDependsOn } : {}),
320
321
  ...(project.targetDependencies ? { targetDependencies: project.targetDependencies } : {}),
321
322
  ...(project.targetExecutors ? { targetExecutors: project.targetExecutors } : {}),
323
+ ...(project.targetOptions ? { targetOptions: project.targetOptions } : {}),
322
324
  ...(project.targetScripts ? { targetScripts: project.targetScripts } : {}),
323
325
  },
324
326
  ]));
@@ -0,0 +1,5 @@
1
+ export interface PrPreviewCleanupWorkflowOptions {
2
+ runsOn?: string | string[];
3
+ }
4
+ export declare function renderPrPreviewCleanupWorkflowYaml(options?: PrPreviewCleanupWorkflowOptions): string;
5
+ //# sourceMappingURL=pr-preview-cleanup-workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr-preview-cleanup-workflow.d.ts","sourceRoot":"","sources":["../../src/monorepo/pr-preview-cleanup-workflow.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,+BAA+B;IAC9C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAgB,kCAAkC,CAAC,OAAO,GAAE,+BAAoC,GAAG,MAAM,CAmCxG"}
@@ -0,0 +1,38 @@
1
+ /* biome-ignore-all lint/suspicious/noTemplateCurlyInString: GitHub Actions expressions are emitted literally. */
2
+ import { renderRunsOnLine } from './github-runs-on.js';
3
+ export function renderPrPreviewCleanupWorkflowYaml(options = {}) {
4
+ return `name: PR Preview Cleanup
5
+
6
+ on:
7
+ pull_request:
8
+ types: [closed]
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ cleanup:
15
+ name: Cleanup PR environment
16
+ if: github.event.pull_request.head.repo.full_name == github.repository
17
+ ${renderRunsOnLine(options.runsOn)}
18
+ timeout-minutes: 15
19
+ defaults:
20
+ run:
21
+ working-directory: tooling/direnv
22
+ steps:
23
+ - name: Checkout
24
+ uses: actions/checkout@v6.0.2
25
+ with:
26
+ filter: blob:none
27
+ fetch-depth: 1
28
+
29
+ - name: Setup Nix/devenv
30
+ uses: ./.github/actions/setup-devenv
31
+
32
+ - name: Cleanup PR environment
33
+ env:
34
+ CLOUDFLARE_API_TOKEN: \${{ secrets.CLOUDFLARE_API_TOKEN }}
35
+ CLOUDFLARE_ACCOUNT_ID: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
36
+ run: smoo wrangler cleanup-pr --pr \${{ github.event.pull_request.number }}
37
+ `;
38
+ }
@@ -380,7 +380,7 @@ function deployProductionStep(step, options) {
380
380
  " ${{ steps.version.outputs.mode != 'none' && inputs.deploy_environment == 'production' && inputs.dry_run !=",
381
381
  " 'true' }}",
382
382
  ...deployEnvLines(options),
383
- ' run: smoo github-ci nx-deploy --configuration production --mode run-many --verify --name "Deploy Production"',
383
+ ' run: smoo github-ci nx-deploy --environment production --mode run-many --verify --name "Deploy Production"',
384
384
  ];
385
385
  }
386
386
  function deployEnvLines(options) {
@@ -557,7 +557,7 @@ function renderMacosPlatformSteps(options) {
557
557
  if (isSmoothBricksCodebasePackageName(options.repoName)) {
558
558
  lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐Ÿ—๏ธ Build self-hosted smoo', ' # SmoothBricks self-hosts smoo from source for release commands.', ' run: nx build cli');
559
559
  }
560
- 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', ' # success() is default; always() still saves GH Nix cache after a red job.', ' if: 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')}`);
560
+ 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: ๐Ÿงช Unit test macOS and iOS packages', ' run:', ` smoo github-ci nx-run-many --targets test --projects-with-targets "${MACOS_PLATFORM_TARGET_GLOBS.join(',')}"`, '', ` # 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', ' # success() is default; always() still saves GH Nix cache after a red job.', ' if: 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')}`);
561
561
  return lines.join('\n').trimEnd();
562
562
  }
563
563
  function renderFinalLinuxPublishSteps(options) {
@@ -606,7 +606,7 @@ function renderFinalLinuxPublishSteps(options) {
606
606
  }
607
607
  lines.push('', ` # Step ${stepNumber++}`, ' - name: ๐ŸŽ Apply verified macOS outputs', ` if: ${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: ${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')}"`);
608
608
  if (options.deploy === true) {
609
- 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"');
609
+ 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 --environment production --mode run-many --verify --name "Deploy Production"');
610
610
  }
611
611
  lines.push('', ' # --- Cleanup ------------------------------------------------------------', '', ` # Step ${stepNumber}`, ' - name: ๐Ÿงน Cleanup and cache Nix/devenv', ' # success() is default; always() still saves GH Nix cache after a red job.', ' if: 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')}`);
612
612
  return lines.join('\n').trimEnd();
@@ -9,8 +9,8 @@ export declare function syncRootRuntimeVersions(root: string): Promise<void>;
9
9
  /**
10
10
  * Validate that package.json runtime pins agree with the LIVE PATH runtimes,
11
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.
12
+ * (Node types float within the runtime major; Bun types stay exact) โ€” the registry
13
+ * is not consulted. Repair: `smoo monorepo init --runtime-only` inside the devenv shell.
14
14
  */
15
15
  export declare function validateRootRuntimeVersions(root: string): Promise<number>;
16
16
  export declare function validateRuntimePins(packageJson: PackageJson, runtime: RuntimeVersions): number;
@@ -1 +1 @@
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"}
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,CA8B9F;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"}
@@ -39,8 +39,8 @@ export async function syncRootRuntimeVersions(root) {
39
39
  /**
40
40
  * Validate that package.json runtime pins agree with the LIVE PATH runtimes,
41
41
  * never a stored template. Offline by design: structural alignment only
42
- * (majors, exact bun pin, no `~major.0.0` floor) โ€” the registry is not
43
- * consulted. Repair: `smoo monorepo init --runtime-only` inside the devenv shell.
42
+ * (Node types float within the runtime major; Bun types stay exact) โ€” the registry
43
+ * is not consulted. Repair: `smoo monorepo init --runtime-only` inside the devenv shell.
44
44
  */
45
45
  export async function validateRootRuntimeVersions(root) {
46
46
  const packageJson = readJsonObject(join(root, 'package.json'));
@@ -68,13 +68,9 @@ export function validateRuntimePins(packageJson, runtime) {
68
68
  failures++;
69
69
  }
70
70
  const typesNode = packageJson.devDependencies?.['@types/node'] ?? null;
71
- const typesNodeParts = typesNode ? /^~(\d+)\.(\d+)\.(\d+)$/.exec(typesNode) : null;
71
+ const typesNodeParts = typesNode ? /^\^(\d+)\.(\d+)\.(\d+)$/.exec(typesNode) : null;
72
72
  if (!typesNodeParts || typesNodeParts[1] !== nodeMajor) {
73
- console.error(`package.json @types/node is ${typesNode ?? 'missing'} but the PATH node is v${runtime.node} โ€” types track the runtime major (~${nodeMajor}.x.y, newest published minor); ${repair}`);
74
- failures++;
75
- }
76
- else if (typesNodeParts[2] === '0' && typesNodeParts[3] === '0') {
77
- console.error(`package.json @types/node is pinned to the ~${nodeMajor}.0.0 floor โ€” tilde locks the first patch line and strands the repo on early broken releases; ${repair} to repin to the newest published ${nodeMajor}.x`);
73
+ console.error(`package.json @types/node is ${typesNode ?? 'missing'} but the PATH node is v${runtime.node} โ€” expected a caret range within the runtime major (^${nodeMajor}.x.y); ${repair}`);
78
74
  failures++;
79
75
  }
80
76
  return failures;
@@ -94,16 +90,15 @@ export function runtimeTypesRangeForPublishedVersions(packageName, runtimeVersio
94
90
  }
95
91
  if (pinMode === 'major') {
96
92
  const runtimeMajor = parsedRuntimeVersion[0].toString();
97
- // Newest published types WITHIN the runtime major โ€” never the `~major.0.0`
98
- // floor: tilde locks the patch line, so the floor can strand consumers on a
99
- // broken early release (e.g. @types/node 24.0.x's URLPattern/DOM TS2403
100
- // conflict, fixed in 24.13) with no path to the repaired minors.
93
+ // Anchor the range at the newest published types in the runtime major. The caret
94
+ // admits later patches and minors without crossing into a different Node major.
101
95
  const latestInMajor = latestVersion(versions.filter((version) => versionMajor(version) === runtimeMajor));
102
- if (latestInMajor) {
103
- return `~${latestInMajor}`;
96
+ if (!latestInMajor) {
97
+ throw new Error(`Unable to find published ${packageName} versions for runtime major ${runtimeMajor}`);
104
98
  }
99
+ return `^${latestInMajor}`;
105
100
  }
106
- else if (versions.includes(runtimeVersion)) {
101
+ if (versions.includes(runtimeVersion)) {
107
102
  return runtimeVersion;
108
103
  }
109
104
  const latest = latestVersion(versions);
@@ -111,7 +106,7 @@ export function runtimeTypesRangeForPublishedVersions(packageName, runtimeVersio
111
106
  throw new Error(`Unable to find any published ${packageName} versions`);
112
107
  }
113
108
  console.warn(`${packageName} has no published types for runtime ${runtimeVersion}; using ${latest}`);
114
- return pinMode === 'major' ? `~${latest}` : latest;
109
+ return latest;
115
110
  }
116
111
  function latestVersion(versions) {
117
112
  let latest = null;
@@ -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;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"}
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;AA4DD,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;AAqCD,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,CAiC7D;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAyBvG;AAyBD,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,CA6B3D;AAoID,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAQxE"}