@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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +24 -1
- package/dist/github-ci/index.d.ts +44 -3
- package/dist/github-ci/index.d.ts.map +1 -1
- package/dist/github-ci/index.js +242 -36
- package/dist/lib/json.d.ts +1 -1
- package/dist/lib/json.d.ts.map +1 -1
- package/dist/lib/json.js +3 -18
- package/dist/lib/workspace.d.ts.map +1 -1
- package/dist/lib/workspace.js +1 -0
- package/dist/monorepo/ci-workflow.js +16 -6
- package/dist/monorepo/managed-files.d.ts +6 -22
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +31 -48
- package/dist/monorepo/package-policy.js +2 -2
- package/dist/monorepo/packs/index.d.ts.map +1 -1
- package/dist/monorepo/packs/index.js +2 -0
- package/dist/monorepo/pr-preview-cleanup-workflow.d.ts +5 -0
- package/dist/monorepo/pr-preview-cleanup-workflow.d.ts.map +1 -0
- package/dist/monorepo/pr-preview-cleanup-workflow.js +38 -0
- package/dist/monorepo/publish-workflow.js +3 -3
- package/dist/monorepo/runtime.d.ts +2 -2
- package/dist/monorepo/runtime.d.ts.map +1 -1
- package/dist/monorepo/runtime.js +11 -16
- package/dist/monorepo/tool-validation.d.ts.map +1 -1
- package/dist/monorepo/tool-validation.js +105 -28
- package/dist/nx/index.d.ts +7 -4
- package/dist/nx/index.d.ts.map +1 -1
- package/dist/nx/index.js +117 -56
- package/dist/playwright/index.d.ts +22 -0
- package/dist/playwright/index.d.ts.map +1 -0
- package/dist/playwright/index.js +44 -0
- package/dist/release/bootstrap-npm-packages.d.ts +3 -0
- package/dist/release/bootstrap-npm-packages.d.ts.map +1 -1
- package/dist/release/bootstrap-npm-packages.js +21 -0
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +17 -0
- package/dist/wrangler/cloudflare.d.ts +85 -0
- package/dist/wrangler/cloudflare.d.ts.map +1 -0
- package/dist/wrangler/cloudflare.js +235 -0
- package/dist/wrangler/deploy-environment.d.ts +48 -0
- package/dist/wrangler/deploy-environment.d.ts.map +1 -0
- package/dist/wrangler/deploy-environment.js +383 -0
- package/dist/wrangler/environment.d.ts +58 -0
- package/dist/wrangler/environment.d.ts.map +1 -0
- package/dist/wrangler/environment.js +297 -0
- package/managed/raw/tooling/devenv +71 -0
- package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +3 -4
- package/package.json +11 -4
- package/src/cli.ts +33 -3
- package/src/github-ci/index.test.ts +221 -1
- package/src/github-ci/index.ts +303 -32
- package/src/lib/json.ts +1 -1
- package/src/lib/workspace.ts +1 -0
- package/src/monorepo/__tests__/ci-workflow.test.ts +10 -4
- package/src/monorepo/__tests__/pr-preview-cleanup-workflow.test.ts +23 -0
- package/src/monorepo/__tests__/publish-workflow.test.ts +12 -4
- package/src/monorepo/ci-workflow.ts +16 -6
- package/src/monorepo/managed-files.test.ts +87 -23
- package/src/monorepo/managed-files.ts +35 -69
- package/src/monorepo/package-policy.test.ts +31 -0
- package/src/monorepo/package-policy.ts +2 -2
- package/src/monorepo/packs/index.ts +2 -0
- package/src/monorepo/pr-preview-cleanup-workflow.ts +44 -0
- package/src/monorepo/publish-workflow.ts +7 -2
- package/src/monorepo/runtime.test.ts +23 -17
- package/src/monorepo/runtime.ts +12 -17
- package/src/monorepo/tool-validation.test.ts +100 -8
- package/src/monorepo/tool-validation.ts +115 -31
- package/src/nx/index.test.ts +45 -14
- package/src/nx/index.ts +133 -64
- package/src/playwright/index.test.ts +90 -0
- package/src/playwright/index.ts +73 -0
- package/src/release/__tests__/bootstrap-npm-packages.test.ts +63 -2
- package/src/release/bootstrap-npm-packages.ts +34 -0
- package/src/release/index.ts +18 -0
- package/src/wrangler/cloudflare.ts +289 -0
- package/src/wrangler/deploy-environment.test.ts +354 -0
- package/src/wrangler/deploy-environment.ts +445 -0
- package/src/wrangler/environment.test.ts +173 -0
- package/src/wrangler/environment.ts +366 -0
- package/managed/raw/patches/ttsc@0.19.3.patch +0 -67
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import typia from 'typia';
|
|
4
4
|
import { cliPackageVersion, isSmoothBricksCodebasePackageName } from '../lib/cli-package.js';
|
|
@@ -40,8 +40,7 @@ const rootDevDependencies = [
|
|
|
40
40
|
},
|
|
41
41
|
{ name: 'nx', fallbackVersion: '23.1.0', minimumVersion: '23.1.0' },
|
|
42
42
|
{ name: 'prettier', fallbackVersion: '^3.6.1', minimumVersion: '3.6.0', prefix: '^' },
|
|
43
|
-
|
|
44
|
-
{ name: 'ttsc', fallbackVersion: '0.19.3' },
|
|
43
|
+
{ name: 'ttsc', fallbackVersion: '0.25.0' },
|
|
45
44
|
// Nx and typescript-eslint still load the TypeScript JS API (6.x).
|
|
46
45
|
// Compilation is exclusively delegated to ttsc by the Nx plugin targets.
|
|
47
46
|
{ name: 'typescript', fallbackVersion: '^6.0.3', minimumVersion: '6.0.0', prefix: '^' },
|
|
@@ -50,14 +49,25 @@ const rootDevDependencies = [
|
|
|
50
49
|
{ name: '@typescript/native', fallbackVersion: 'npm:typescript@^7.0.2' },
|
|
51
50
|
];
|
|
52
51
|
const cliPackageName = '@smoothbricks/cli';
|
|
53
|
-
const requiredDevenvPackages = ['bun', 'git', 'git-format-staged', 'jq', 'alejandra', 'coreutils', 'gnutar'];
|
|
52
|
+
const requiredDevenvPackages = ['bun', 'git', 'git-format-staged', 'jq', 'alejandra', 'coreutils', 'gnutar', 'go'];
|
|
54
53
|
// Any explicit nodejs provider is fine — the pinned major is the repo's choice
|
|
55
54
|
// (Lambda parity, org convergence, …). Whether the pins in package.json agree
|
|
56
55
|
// with the runtime is validated against the live PATH (validateRootRuntimeVersions),
|
|
57
56
|
// never against a version template here.
|
|
58
57
|
const nodePackagePattern = /(^|\s)nodejs(_\d+|_latest)?(\s|#|$)/m;
|
|
59
|
-
const
|
|
60
|
-
const
|
|
58
|
+
const requiredRustDevenvPackages = ['sccache'];
|
|
59
|
+
const linuxCompilerPackage = 'pkgs.stdenv.cc';
|
|
60
|
+
const ignoredNativeManifestDirectories = new Set([
|
|
61
|
+
'.devenv',
|
|
62
|
+
'.direnv',
|
|
63
|
+
'.git',
|
|
64
|
+
'.nx',
|
|
65
|
+
'dist',
|
|
66
|
+
'node_modules',
|
|
67
|
+
'target',
|
|
68
|
+
'vendor',
|
|
69
|
+
]);
|
|
70
|
+
const obsoleteTtscPatchedDependencyKey = 'ttsc@0.19.3';
|
|
61
71
|
export async function applyToolConfigDefaults(root) {
|
|
62
72
|
const context = await readToolContext(root);
|
|
63
73
|
await applyRootPackageToolDefaults(root, context);
|
|
@@ -67,7 +77,7 @@ export async function applyToolConfigDefaults(root) {
|
|
|
67
77
|
export async function validateToolConfig(root) {
|
|
68
78
|
const context = await readToolContext(root);
|
|
69
79
|
return (validateRootDevDependencies(context.policy, context.rootPackage) +
|
|
70
|
-
|
|
80
|
+
validateObsoleteTtscPatchRemoved(context.rootPackage) +
|
|
71
81
|
validateToolingPackage(root, context.policy) +
|
|
72
82
|
validateToolingWorkspace(context.rootPackage) +
|
|
73
83
|
validateDevenvPackages(root));
|
|
@@ -89,7 +99,7 @@ export async function applyRootDevDependencyDefaults(root, context) {
|
|
|
89
99
|
if (delete devDependencies['@smoothbricks/cli']) {
|
|
90
100
|
changed = true;
|
|
91
101
|
}
|
|
92
|
-
changed =
|
|
102
|
+
changed = removeObsoleteTtscPatch(pkg) || changed;
|
|
93
103
|
if (changed) {
|
|
94
104
|
writeJsonObject(join(root, 'package.json'), pkg);
|
|
95
105
|
console.log('updated package.json workspace tool dependencies');
|
|
@@ -105,7 +115,6 @@ async function applyRootPackageToolDefaults(root, context) {
|
|
|
105
115
|
}
|
|
106
116
|
let dependencyChanged = false;
|
|
107
117
|
let workspaceChanged = false;
|
|
108
|
-
let patchChanged = false;
|
|
109
118
|
const devDependencies = ensureDependencyMap(pkg, 'devDependencies');
|
|
110
119
|
for (const dependency of rootDevDependencies) {
|
|
111
120
|
const current = devDependencies[dependency.name];
|
|
@@ -118,8 +127,8 @@ async function applyRootPackageToolDefaults(root, context) {
|
|
|
118
127
|
dependencyChanged = true;
|
|
119
128
|
}
|
|
120
129
|
workspaceChanged = addWorkspacePattern(pkg, 'tooling');
|
|
121
|
-
|
|
122
|
-
if (dependencyChanged || workspaceChanged
|
|
130
|
+
dependencyChanged = removeObsoleteTtscPatch(pkg) || dependencyChanged;
|
|
131
|
+
if (dependencyChanged || workspaceChanged) {
|
|
123
132
|
writeJsonObject(join(root, 'package.json'), pkg);
|
|
124
133
|
}
|
|
125
134
|
console.log(dependencyChanged
|
|
@@ -128,9 +137,6 @@ async function applyRootPackageToolDefaults(root, context) {
|
|
|
128
137
|
console.log(workspaceChanged
|
|
129
138
|
? 'updated package.json tooling workspace'
|
|
130
139
|
: 'unchanged package.json tooling workspace');
|
|
131
|
-
console.log(patchChanged
|
|
132
|
-
? 'updated package.json patchedDependencies for ttsc'
|
|
133
|
-
: 'unchanged package.json patchedDependencies for ttsc');
|
|
134
140
|
}
|
|
135
141
|
export function applyToolingPackageDefaults(root, policy) {
|
|
136
142
|
const path = join(root, 'tooling', 'package.json');
|
|
@@ -178,7 +184,9 @@ export function applyDevenvPackageDefaults(root) {
|
|
|
178
184
|
changed = next !== content || changed;
|
|
179
185
|
content = next;
|
|
180
186
|
}
|
|
181
|
-
|
|
187
|
+
const compilesRust = workspaceCompilesRust(root);
|
|
188
|
+
const requiredPackages = [...requiredDevenvPackages, ...(compilesRust ? requiredRustDevenvPackages : [])];
|
|
189
|
+
for (const name of requiredPackages) {
|
|
182
190
|
if (hasNixPackage(content, name)) {
|
|
183
191
|
continue;
|
|
184
192
|
}
|
|
@@ -186,6 +194,11 @@ export function applyDevenvPackageDefaults(root) {
|
|
|
186
194
|
changed = next !== content || changed;
|
|
187
195
|
content = next;
|
|
188
196
|
}
|
|
197
|
+
if (compilesRust && !hasLinuxCompilerPackage(content)) {
|
|
198
|
+
const next = addLinuxCompilerPackage(content);
|
|
199
|
+
changed = next !== content || changed;
|
|
200
|
+
content = next;
|
|
201
|
+
}
|
|
189
202
|
if (changed) {
|
|
190
203
|
writeFileSync(path, content);
|
|
191
204
|
console.log('updated tooling/direnv/devenv.nix packages');
|
|
@@ -219,20 +232,23 @@ export function validateRootDevDependencies(policy, rootPackage) {
|
|
|
219
232
|
}
|
|
220
233
|
return failures;
|
|
221
234
|
}
|
|
222
|
-
function
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
function validateTtscPatchedDependency(rootPackage) {
|
|
227
|
-
if (!rootPackage) {
|
|
228
|
-
return 0;
|
|
235
|
+
function removeObsoleteTtscPatch(pkg) {
|
|
236
|
+
const patchedDependencies = pkg.patchedDependencies;
|
|
237
|
+
if (!patchedDependencies || !(obsoleteTtscPatchedDependencyKey in patchedDependencies)) {
|
|
238
|
+
return false;
|
|
229
239
|
}
|
|
230
|
-
|
|
231
|
-
if (
|
|
240
|
+
delete patchedDependencies[obsoleteTtscPatchedDependencyKey];
|
|
241
|
+
if (Object.keys(patchedDependencies).length === 0) {
|
|
242
|
+
delete pkg.patchedDependencies;
|
|
243
|
+
}
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
function validateObsoleteTtscPatchRemoved(rootPackage) {
|
|
247
|
+
const patchedDependencies = rootPackage?.patchedDependencies;
|
|
248
|
+
if (!patchedDependencies || !(obsoleteTtscPatchedDependencyKey in patchedDependencies)) {
|
|
232
249
|
return 0;
|
|
233
250
|
}
|
|
234
|
-
console.error(`package.json patchedDependencies.${
|
|
235
|
-
(typeof actual === 'string' ? `; found ${actual}` : ' (required for declaration-emit fix)'));
|
|
251
|
+
console.error(`package.json patchedDependencies.${obsoleteTtscPatchedDependencyKey} must be removed; ttsc 0.25.0 emits typia declarations without the obsolete patch`);
|
|
236
252
|
return 1;
|
|
237
253
|
}
|
|
238
254
|
export function validateToolingPackage(root, policy) {
|
|
@@ -280,12 +296,18 @@ export function validateDevenvPackages(root) {
|
|
|
280
296
|
console.error('tooling/direnv/devenv.nix packages must include a nodejs provider (nodejs_<major> or nodejs_latest)');
|
|
281
297
|
failures++;
|
|
282
298
|
}
|
|
283
|
-
|
|
299
|
+
const compilesRust = workspaceCompilesRust(root);
|
|
300
|
+
const requiredPackages = [...requiredDevenvPackages, ...(compilesRust ? requiredRustDevenvPackages : [])];
|
|
301
|
+
for (const name of requiredPackages) {
|
|
284
302
|
if (!hasNixPackage(content, name)) {
|
|
285
303
|
console.error(`tooling/direnv/devenv.nix packages must include ${name}`);
|
|
286
304
|
failures++;
|
|
287
305
|
}
|
|
288
306
|
}
|
|
307
|
+
if (compilesRust && !hasLinuxCompilerPackage(content)) {
|
|
308
|
+
console.error('tooling/direnv/devenv.nix packages must include pkgs.stdenv.cc in a Linux-only package block for Rust builds');
|
|
309
|
+
failures++;
|
|
310
|
+
}
|
|
289
311
|
return failures;
|
|
290
312
|
}
|
|
291
313
|
function addNixPackage(content, name, comment) {
|
|
@@ -293,7 +315,9 @@ function addNixPackage(content, name, comment) {
|
|
|
293
315
|
if (hasNixPackage(content, name)) {
|
|
294
316
|
return content;
|
|
295
317
|
}
|
|
296
|
-
const
|
|
318
|
+
const directPackagesStart = content.indexOf(' packages = with pkgs; [');
|
|
319
|
+
const groupedPackagesStart = content.indexOf(' (with pkgs; [');
|
|
320
|
+
const packagesStart = directPackagesStart === -1 ? groupedPackagesStart : directPackagesStart;
|
|
297
321
|
if (packagesStart === -1) {
|
|
298
322
|
return content;
|
|
299
323
|
}
|
|
@@ -303,6 +327,53 @@ function addNixPackage(content, name, comment) {
|
|
|
303
327
|
function hasNixPackage(content, name) {
|
|
304
328
|
return new RegExp(`(^|\\s)${escapeRegex(name)}(\\s|#|$)`, 'm').test(content);
|
|
305
329
|
}
|
|
330
|
+
function workspaceCompilesRust(root) {
|
|
331
|
+
return containsCargoManifest(root);
|
|
332
|
+
}
|
|
333
|
+
function containsCargoManifest(directory) {
|
|
334
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
335
|
+
if (entry.isFile() && entry.name === 'Cargo.toml') {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
if (entry.isDirectory() &&
|
|
339
|
+
entry.name.startsWith('.') === false &&
|
|
340
|
+
ignoredNativeManifestDirectories.has(entry.name) === false &&
|
|
341
|
+
containsCargoManifest(join(directory, entry.name))) {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
function hasLinuxCompilerPackage(content) {
|
|
348
|
+
const linuxPackages = /\+\+\s+lib\.optionals\s+pkgs\.stdenv\.isLinux\s+\[([\s\S]*?)\]/g;
|
|
349
|
+
return [...content.matchAll(linuxPackages)].some((match) => hasNixPackage(match[1] ?? '', linuxCompilerPackage));
|
|
350
|
+
}
|
|
351
|
+
function addLinuxCompilerPackage(content) {
|
|
352
|
+
if (hasLinuxCompilerPackage(content)) {
|
|
353
|
+
return content;
|
|
354
|
+
}
|
|
355
|
+
const directStart = content.indexOf(' packages = with pkgs; [');
|
|
356
|
+
if (directStart !== -1) {
|
|
357
|
+
const listEnd = content.indexOf('\n ];', directStart);
|
|
358
|
+
if (listEnd === -1) {
|
|
359
|
+
return content;
|
|
360
|
+
}
|
|
361
|
+
const listBody = content.slice(directStart + ' packages = with pkgs; ['.length, listEnd);
|
|
362
|
+
const replacement = ` packages =\n (with pkgs; [${listBody}\n ])\n ++ lib.optionals pkgs.stdenv.isLinux [\n ${linuxCompilerPackage}\n ];`;
|
|
363
|
+
return `${content.slice(0, directStart)}${replacement}${content.slice(listEnd + '\n ];'.length)}`;
|
|
364
|
+
}
|
|
365
|
+
const packagesStart = content.indexOf(' packages =');
|
|
366
|
+
const nextOption = content.indexOf('\n\n ', packagesStart);
|
|
367
|
+
if (packagesStart === -1 || nextOption === -1) {
|
|
368
|
+
return content;
|
|
369
|
+
}
|
|
370
|
+
const terminator = content.lastIndexOf(';', nextOption);
|
|
371
|
+
if (terminator < packagesStart) {
|
|
372
|
+
return content;
|
|
373
|
+
}
|
|
374
|
+
const linuxPackages = `\n ++ lib.optionals pkgs.stdenv.isLinux [\n ${linuxCompilerPackage}\n ]`;
|
|
375
|
+
return `${content.slice(0, terminator)}${linuxPackages}${content.slice(terminator)}`;
|
|
376
|
+
}
|
|
306
377
|
function nixPackageComment(name) {
|
|
307
378
|
if (name === 'coreutils') {
|
|
308
379
|
return '# Provides fmt for commit message wrapping';
|
|
@@ -313,6 +384,12 @@ function nixPackageComment(name) {
|
|
|
313
384
|
if (name === 'git') {
|
|
314
385
|
return '# Git hooks and repository inspection';
|
|
315
386
|
}
|
|
387
|
+
if (name === 'go') {
|
|
388
|
+
return '# Builds ttsc source plugins';
|
|
389
|
+
}
|
|
390
|
+
if (name === 'sccache') {
|
|
391
|
+
return '# Rust compiler wrapper and cache';
|
|
392
|
+
}
|
|
316
393
|
return '';
|
|
317
394
|
}
|
|
318
395
|
function escapeRegex(value) {
|
package/dist/nx/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { NxProjectJson, NxTargetConfig, NxTargetOptions } from '../lib/json.js';
|
|
2
2
|
export interface ProjectTargets {
|
|
3
3
|
project: string;
|
|
4
4
|
root?: string;
|
|
@@ -6,6 +6,7 @@ export interface ProjectTargets {
|
|
|
6
6
|
buildDependsOn?: string[];
|
|
7
7
|
targetDependencies?: Map<string, string[]>;
|
|
8
8
|
targetExecutors?: Map<string, string>;
|
|
9
|
+
targetOptions?: Map<string, NxTargetOptions>;
|
|
9
10
|
targetOutputs?: Map<string, string[]>;
|
|
10
11
|
targetScripts?: Map<string, string>;
|
|
11
12
|
}
|
|
@@ -14,24 +15,26 @@ export interface CommandInvocation {
|
|
|
14
15
|
args: string[];
|
|
15
16
|
}
|
|
16
17
|
export declare function nxResetCommand(): CommandInvocation;
|
|
17
|
-
export declare function nxShowProjectCommand(project: string): CommandInvocation;
|
|
18
18
|
export declare function nxCacheDirectories(root: string): string[];
|
|
19
19
|
export declare function targetNamesFromNxProjectJson(value: NxProjectJson | null | undefined): string[];
|
|
20
20
|
export declare function projectRootFromNxProjectJson(value: NxProjectJson | null | undefined): string | undefined;
|
|
21
|
-
export declare function buildDependsOnFromNxProjectJson(value: NxProjectJson | null | undefined): string[] | undefined;
|
|
22
21
|
export declare function targetDependenciesFromNxProjectJson(value: NxProjectJson | null | undefined): Map<string, string[]>;
|
|
23
22
|
export declare function targetExecutorsFromNxProjectJson(value: NxProjectJson | null | undefined): Map<string, string>;
|
|
23
|
+
export declare function targetOptionsFromNxProjectJson(value: NxProjectJson | null | undefined): Map<string, NxTargetOptions>;
|
|
24
24
|
export declare function targetOutputsFromNxProjectJson(value: NxProjectJson | null | undefined): Map<string, string[]>;
|
|
25
25
|
export declare function targetScriptsFromNxProjectJson(value: NxProjectJson | null | undefined): Map<string, string>;
|
|
26
26
|
export declare function formatProjectTargetLines(projects: ProjectTargets[]): string;
|
|
27
27
|
export declare function projectNamesWithTarget(projects: ProjectTargets[], target: string): string[];
|
|
28
|
-
export declare function projectNamesFromNxShowProjectsOutput(output: string): string[];
|
|
29
28
|
export declare function listTargets(root: string): Promise<void>;
|
|
30
29
|
export declare function listProjects(root: string, options: {
|
|
31
30
|
withTarget?: string;
|
|
32
31
|
}): Promise<void>;
|
|
33
32
|
export declare function resetCache(root: string): Promise<void>;
|
|
34
33
|
export declare function cleanCache(root: string): Promise<void>;
|
|
34
|
+
export type NxProjects = Readonly<Record<string, NxProjectJson>>;
|
|
35
|
+
export declare function loadNxProjects(root: string): Promise<NxProjects>;
|
|
36
|
+
export declare function targetNamesFromProjects(projects: NxProjects): string[];
|
|
37
|
+
export declare function projectTargetsFromNxProjects(projects: NxProjects): ProjectTargets[];
|
|
35
38
|
export declare function readProjectTargets(root: string): Promise<ProjectTargets[]>;
|
|
36
39
|
export type { NxProjectJson, NxTargetConfig };
|
|
37
40
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/nx/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nx/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nx/index.ts"],"names":[],"mappings":"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"}
|
package/dist/nx/index.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { lstat, rm } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
// Nx package exports are CLI-oriented; this is the module the CLI uses for graph + daemon IPC.
|
|
5
|
+
import { createProjectGraphAsync } from 'nx/src/project-graph/project-graph.js';
|
|
6
|
+
import { workspaceRoot as primaryWorkspaceRoot } from 'nx/src/utils/workspace-root.js';
|
|
7
|
+
import { run, runResult } from '../lib/run.js';
|
|
7
8
|
export function nxResetCommand() {
|
|
8
9
|
return { command: 'nx', args: ['reset'] };
|
|
9
10
|
}
|
|
10
|
-
export function nxShowProjectCommand(project) {
|
|
11
|
-
return { command: 'nx', args: ['show', 'project', project, '--json'] };
|
|
12
|
-
}
|
|
13
11
|
export function nxCacheDirectories(root) {
|
|
14
12
|
return [join(root, '.nx/cache'), join(root, '.nx/workspace-data'), join(root, 'node_modules/.cache/nx')];
|
|
15
13
|
}
|
|
@@ -20,9 +18,6 @@ export function targetNamesFromNxProjectJson(value) {
|
|
|
20
18
|
export function projectRootFromNxProjectJson(value) {
|
|
21
19
|
return typeof value?.root === 'string' ? value.root : undefined;
|
|
22
20
|
}
|
|
23
|
-
export function buildDependsOnFromNxProjectJson(value) {
|
|
24
|
-
return targetDependenciesFromNxProjectJson(value).get('build');
|
|
25
|
-
}
|
|
26
21
|
export function targetDependenciesFromNxProjectJson(value) {
|
|
27
22
|
const targets = value?.targets;
|
|
28
23
|
const dependencies = new Map();
|
|
@@ -79,6 +74,19 @@ export function targetExecutorsFromNxProjectJson(value) {
|
|
|
79
74
|
}
|
|
80
75
|
return executors;
|
|
81
76
|
}
|
|
77
|
+
export function targetOptionsFromNxProjectJson(value) {
|
|
78
|
+
const targets = value?.targets;
|
|
79
|
+
const options = new Map();
|
|
80
|
+
if (!targets) {
|
|
81
|
+
return options;
|
|
82
|
+
}
|
|
83
|
+
for (const [targetName, target] of Object.entries(targets)) {
|
|
84
|
+
if (target.options) {
|
|
85
|
+
options.set(targetName, target.options);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return options;
|
|
89
|
+
}
|
|
82
90
|
export function targetOutputsFromNxProjectJson(value) {
|
|
83
91
|
return targetStringArraysFromNxProjectJson(value, 'outputs');
|
|
84
92
|
}
|
|
@@ -127,28 +135,6 @@ export function projectNamesWithTarget(projects, target) {
|
|
|
127
135
|
.map((project) => project.project)
|
|
128
136
|
.sort((a, b) => a.localeCompare(b));
|
|
129
137
|
}
|
|
130
|
-
export function projectNamesFromNxShowProjectsOutput(output) {
|
|
131
|
-
const trimmed = output.trim();
|
|
132
|
-
if (!trimmed) {
|
|
133
|
-
return [];
|
|
134
|
-
}
|
|
135
|
-
if (trimmed.startsWith('[')) {
|
|
136
|
-
try {
|
|
137
|
-
const parsed = parseStringArrayText(trimmed);
|
|
138
|
-
if (parsed) {
|
|
139
|
-
return parsed.sort((a, b) => a.localeCompare(b));
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
// Fall through to legacy newline parsing for older Nx output shapes.
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return trimmed
|
|
147
|
-
.split('\n')
|
|
148
|
-
.map((line) => line.trim())
|
|
149
|
-
.filter(Boolean)
|
|
150
|
-
.sort((a, b) => a.localeCompare(b));
|
|
151
|
-
}
|
|
152
138
|
export async function listTargets(root) {
|
|
153
139
|
const output = formatProjectTargetLines(await readProjectTargets(root));
|
|
154
140
|
if (output) {
|
|
@@ -182,30 +168,105 @@ export async function cleanCache(root) {
|
|
|
182
168
|
console.log(`Removed ${path}`);
|
|
183
169
|
}
|
|
184
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Load the resolved project graph through Nx's API. The current workspace uses the
|
|
173
|
+
* daemon in-process; foreign roots use an isolated process because Nx snapshots its
|
|
174
|
+
* workspace cache paths when the module loads.
|
|
175
|
+
*/
|
|
176
|
+
let graphLoadTail = Promise.resolve();
|
|
177
|
+
export function loadNxProjects(root) {
|
|
178
|
+
const result = graphLoadTail.then(() => loadNxProjectsNow(root));
|
|
179
|
+
graphLoadTail = result.then(() => undefined, () => undefined);
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
async function loadNxProjectsNow(root) {
|
|
183
|
+
if (root !== primaryWorkspaceRoot) {
|
|
184
|
+
return loadForeignNxProjects(root);
|
|
185
|
+
}
|
|
186
|
+
const graph = await createProjectGraphAsync({ exitOnError: false });
|
|
187
|
+
return nxProjectsFromNodes(graph.nodes);
|
|
188
|
+
}
|
|
189
|
+
const FOREIGN_GRAPH_SCRIPT = `
|
|
190
|
+
import('nx/src/project-graph/project-graph.js')
|
|
191
|
+
.then(async ({ createProjectGraphAsync }) => {
|
|
192
|
+
const graph = await createProjectGraphAsync({ exitOnError: false });
|
|
193
|
+
const projects = Object.fromEntries(
|
|
194
|
+
Object.entries(graph.nodes).map(([name, node]) => [
|
|
195
|
+
name,
|
|
196
|
+
{ ...node.data, name: node.data?.name ?? name, targets: node.data?.targets ?? {} },
|
|
197
|
+
]),
|
|
198
|
+
);
|
|
199
|
+
process.stdout.write(JSON.stringify(projects));
|
|
200
|
+
})
|
|
201
|
+
.catch((error) => {
|
|
202
|
+
console.error(error);
|
|
203
|
+
process.exitCode = 1;
|
|
204
|
+
});
|
|
205
|
+
`;
|
|
206
|
+
async function loadForeignNxProjects(root) {
|
|
207
|
+
const result = await runResult(process.execPath, ['--eval', FOREIGN_GRAPH_SCRIPT], root, {
|
|
208
|
+
NX_DAEMON: 'false',
|
|
209
|
+
NX_ISOLATE_PLUGINS: 'false',
|
|
210
|
+
NX_WORKSPACE_ROOT_PATH: root,
|
|
211
|
+
});
|
|
212
|
+
if (result.exitCode !== 0) {
|
|
213
|
+
throw new Error(`Failed to load Nx project graph for ${root}: ${result.stderr.trim()}`);
|
|
214
|
+
}
|
|
215
|
+
const parsed = JSON.parse(result.stdout);
|
|
216
|
+
if (!isNxProjects(parsed)) {
|
|
217
|
+
throw new Error(`Nx returned an invalid project graph for ${root}`);
|
|
218
|
+
}
|
|
219
|
+
return parsed;
|
|
220
|
+
}
|
|
221
|
+
function nxProjectsFromNodes(nodes) {
|
|
222
|
+
const projects = {};
|
|
223
|
+
for (const [name, node] of Object.entries(nodes)) {
|
|
224
|
+
projects[name] = {
|
|
225
|
+
...node.data,
|
|
226
|
+
name: node.data.name ?? name,
|
|
227
|
+
targets: node.data.targets ?? {},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return projects;
|
|
231
|
+
}
|
|
232
|
+
function isNxProjects(value) {
|
|
233
|
+
if (!isRecord(value))
|
|
234
|
+
return false;
|
|
235
|
+
return Object.values(value).every((project) => isRecord(project) &&
|
|
236
|
+
(project.name === undefined || typeof project.name === 'string') &&
|
|
237
|
+
(project.root === undefined || typeof project.root === 'string') &&
|
|
238
|
+
(project.targets === undefined || (isRecord(project.targets) && Object.values(project.targets).every(isRecord))));
|
|
239
|
+
}
|
|
240
|
+
function isRecord(value) {
|
|
241
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
242
|
+
}
|
|
243
|
+
export function targetNamesFromProjects(projects) {
|
|
244
|
+
const names = new Set();
|
|
245
|
+
for (const project of Object.values(projects)) {
|
|
246
|
+
for (const targetName of targetNamesFromNxProjectJson(project)) {
|
|
247
|
+
names.add(targetName);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return [...names];
|
|
251
|
+
}
|
|
252
|
+
export function projectTargetsFromNxProjects(projects) {
|
|
253
|
+
return Object.entries(projects)
|
|
254
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
255
|
+
.map(([project, metadata]) => {
|
|
256
|
+
const targetDependencies = targetDependenciesFromNxProjectJson(metadata);
|
|
257
|
+
return {
|
|
258
|
+
project,
|
|
259
|
+
root: projectRootFromNxProjectJson(metadata),
|
|
260
|
+
targets: targetNamesFromNxProjectJson(metadata),
|
|
261
|
+
buildDependsOn: targetDependencies.get('build'),
|
|
262
|
+
targetDependencies,
|
|
263
|
+
targetExecutors: targetExecutorsFromNxProjectJson(metadata),
|
|
264
|
+
targetOptions: targetOptionsFromNxProjectJson(metadata),
|
|
265
|
+
targetOutputs: targetOutputsFromNxProjectJson(metadata),
|
|
266
|
+
targetScripts: targetScriptsFromNxProjectJson(metadata),
|
|
267
|
+
};
|
|
268
|
+
});
|
|
269
|
+
}
|
|
185
270
|
export async function readProjectTargets(root) {
|
|
186
|
-
|
|
187
|
-
return Promise.all(projects.map((project) => readProjectTarget(root, project)));
|
|
188
|
-
}
|
|
189
|
-
async function readNxProjectNames(root) {
|
|
190
|
-
const result = await $ `nx show projects`.cwd(root).quiet();
|
|
191
|
-
return projectNamesFromNxShowProjectsOutput(decode(result.stdout));
|
|
192
|
-
}
|
|
193
|
-
async function readProjectTarget(root, project) {
|
|
194
|
-
const command = nxShowProjectCommand(project);
|
|
195
|
-
const result = await $ `${command.command} ${command.args}`.cwd(root).quiet();
|
|
196
|
-
const parsed = parseNxProjectJsonText(decode(result.stdout));
|
|
197
|
-
if (!parsed) {
|
|
198
|
-
throw new Error(`Unable to inspect Nx project ${project}.`);
|
|
199
|
-
}
|
|
200
|
-
const targetDependencies = targetDependenciesFromNxProjectJson(parsed);
|
|
201
|
-
return {
|
|
202
|
-
project,
|
|
203
|
-
root: projectRootFromNxProjectJson(parsed),
|
|
204
|
-
targets: targetNamesFromNxProjectJson(parsed),
|
|
205
|
-
buildDependsOn: targetDependencies.get('build'),
|
|
206
|
-
targetDependencies,
|
|
207
|
-
targetExecutors: targetExecutorsFromNxProjectJson(parsed),
|
|
208
|
-
targetOutputs: targetOutputsFromNxProjectJson(parsed),
|
|
209
|
-
targetScripts: targetScriptsFromNxProjectJson(parsed),
|
|
210
|
-
};
|
|
271
|
+
return projectTargetsFromNxProjects(await loadNxProjects(root));
|
|
211
272
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ChromiumSetupDependencies {
|
|
2
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
3
|
+
readonly exists: (path: string) => boolean;
|
|
4
|
+
readonly run: (command: string, args: string[], cwd: string, env?: Record<string, string>) => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export type ChromiumSetupResult = {
|
|
7
|
+
readonly mode: 'persistent-cache';
|
|
8
|
+
readonly browserCachePath: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly mode: 'system';
|
|
11
|
+
readonly executablePath: string;
|
|
12
|
+
} | {
|
|
13
|
+
readonly mode: 'developer-cache';
|
|
14
|
+
readonly browserCachePath?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Ensure Chromium is available without polluting ephemeral GitHub runners.
|
|
18
|
+
* Persistent host runners and developer machines may install into their
|
|
19
|
+
* respective caches; ephemeral GitHub runners must use their image's browser.
|
|
20
|
+
*/
|
|
21
|
+
export declare function ensureChromium(cwd?: string, dependencies?: ChromiumSetupDependencies): Promise<ChromiumSetupResult>;
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/playwright/index.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7G;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAQ7E;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,GAAG,SAAgB,EACnB,YAAY,GAAE,yBAA+C,GAC5D,OAAO,CAAC,mBAAmB,CAAC,CAmC9B"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { run } from '../lib/run.js';
|
|
3
|
+
const HOST_CACHE_ROOT = '/var/cache/ci';
|
|
4
|
+
const HOST_BROWSER_CACHE = `${HOST_CACHE_ROOT}/ms-playwright`;
|
|
5
|
+
const SYSTEM_CHROME_PATHS = [
|
|
6
|
+
'/usr/bin/google-chrome',
|
|
7
|
+
'/usr/bin/chromium-browser',
|
|
8
|
+
'/usr/bin/chromium',
|
|
9
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
10
|
+
];
|
|
11
|
+
const defaultDependencies = {
|
|
12
|
+
env: process.env,
|
|
13
|
+
exists: existsSync,
|
|
14
|
+
run,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Ensure Chromium is available without polluting ephemeral GitHub runners.
|
|
18
|
+
* Persistent host runners and developer machines may install into their
|
|
19
|
+
* respective caches; ephemeral GitHub runners must use their image's browser.
|
|
20
|
+
*/
|
|
21
|
+
export async function ensureChromium(cwd = process.cwd(), dependencies = defaultDependencies) {
|
|
22
|
+
const { env, exists, run: runCommand } = dependencies;
|
|
23
|
+
const githubActions = env.GITHUB_ACTIONS === 'true';
|
|
24
|
+
if (githubActions && exists(HOST_CACHE_ROOT)) {
|
|
25
|
+
await runCommand('playwright', ['install', 'chromium', '--only-shell'], cwd, {
|
|
26
|
+
PLAYWRIGHT_BROWSERS_PATH: HOST_BROWSER_CACHE,
|
|
27
|
+
});
|
|
28
|
+
console.log(`Chromium ready in persistent cache: ${HOST_BROWSER_CACHE}`);
|
|
29
|
+
return { mode: 'persistent-cache', browserCachePath: HOST_BROWSER_CACHE };
|
|
30
|
+
}
|
|
31
|
+
if (githubActions) {
|
|
32
|
+
const candidates = [env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH, ...SYSTEM_CHROME_PATHS].filter((path) => typeof path === 'string' && path.length > 0);
|
|
33
|
+
const executablePath = candidates.find(exists);
|
|
34
|
+
if (!executablePath) {
|
|
35
|
+
throw new Error(`GitHub-hosted runner has no preinstalled Chromium. Refusing to download; searched: ${candidates.join(', ')}`);
|
|
36
|
+
}
|
|
37
|
+
console.log(`Using preinstalled Chromium: ${executablePath}`);
|
|
38
|
+
return { mode: 'system', executablePath };
|
|
39
|
+
}
|
|
40
|
+
const browserCachePath = env.PLAYWRIGHT_BROWSERS_PATH;
|
|
41
|
+
await runCommand('playwright', ['install', 'chromium', '--only-shell'], cwd, browserCachePath ? { PLAYWRIGHT_BROWSERS_PATH: browserCachePath } : undefined);
|
|
42
|
+
console.log(browserCachePath ? `Chromium ready in configured cache: ${browserCachePath}` : 'Chromium ready.');
|
|
43
|
+
return browserCachePath ? { mode: 'developer-cache', browserCachePath } : { mode: 'developer-cache' };
|
|
44
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReleasePackageInfo } from './core.js';
|
|
2
2
|
export declare const NPM_BOOTSTRAP_VERSION = "0.0.0-bootstrap.0";
|
|
3
3
|
export declare const NPM_BOOTSTRAP_DIST_TAG = "bootstrap";
|
|
4
|
+
export declare const NPM_BOOTSTRAP_VISIBILITY_TIMEOUT_MS = 120000;
|
|
4
5
|
export interface BootstrapNpmPackagesOptions {
|
|
5
6
|
dryRun: boolean;
|
|
6
7
|
skipLogin: boolean;
|
|
@@ -10,9 +11,11 @@ export interface BootstrapNpmPackagesOptions {
|
|
|
10
11
|
export interface BootstrapNpmPackagesShell<Package extends ReleasePackageInfo = ReleasePackageInfo> {
|
|
11
12
|
listReleasePackages(): Package[];
|
|
12
13
|
packageExists(name: string): Promise<boolean>;
|
|
14
|
+
packageVersionExists(name: string, version: string): Promise<boolean>;
|
|
13
15
|
login(): Promise<void>;
|
|
14
16
|
publishPlaceholder(pkg: Package, env?: Record<string, string>): Promise<void>;
|
|
15
17
|
promptOtp(packageName: string): Promise<string>;
|
|
18
|
+
wait(milliseconds: number): Promise<void>;
|
|
16
19
|
log(message: string): void;
|
|
17
20
|
}
|
|
18
21
|
export declare function bootstrapNpmPackages<Package extends ReleasePackageInfo>(shell: BootstrapNpmPackagesShell<Package>, options: BootstrapNpmPackagesOptions): Promise<Package[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap-npm-packages.d.ts","sourceRoot":"","sources":["../../src/release/bootstrap-npm-packages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,eAAO,MAAM,sBAAsB,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"bootstrap-npm-packages.d.ts","sourceRoot":"","sources":["../../src/release/bootstrap-npm-packages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AACzD,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAClD,eAAO,MAAM,mCAAmC,SAAU,CAAC;AAI3D,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,yBAAyB,CAAC,OAAO,SAAS,kBAAkB,GAAG,kBAAkB;IAChG,mBAAmB,IAAI,OAAO,EAAE,CAAC;IACjC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAsB,oBAAoB,CAAC,OAAO,SAAS,kBAAkB,EAC3E,KAAK,EAAE,yBAAyB,CAAC,OAAO,CAAC,EACzC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,OAAO,EAAE,CAAC,CA2CpB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const NPM_BOOTSTRAP_VERSION = '0.0.0-bootstrap.0';
|
|
2
2
|
export const NPM_BOOTSTRAP_DIST_TAG = 'bootstrap';
|
|
3
|
+
export const NPM_BOOTSTRAP_VISIBILITY_TIMEOUT_MS = 120000;
|
|
4
|
+
const NPM_BOOTSTRAP_POLL_DELAYS_MS = [0, 1000, 2000, 4000, 8000, 15000, 30000, 30000, 30000];
|
|
3
5
|
export async function bootstrapNpmPackages(shell, options) {
|
|
4
6
|
const packages = selectedReleasePackages(shell.listReleasePackages(), options.packages);
|
|
5
7
|
if (packages.length === 0) {
|
|
@@ -27,14 +29,33 @@ export async function bootstrapNpmPackages(shell, options) {
|
|
|
27
29
|
if (!options.skipLogin) {
|
|
28
30
|
await shell.login();
|
|
29
31
|
}
|
|
32
|
+
// Upload every placeholder before waiting for npm registry propagation. Keeping the
|
|
33
|
+
// phases separate prevents one slow package from blocking the remaining uploads.
|
|
30
34
|
for (const pkg of missing) {
|
|
31
35
|
shell.log(`${pkg.name}: publishing npm placeholder.`);
|
|
32
36
|
const otp = options.otp ?? (await shell.promptOtp(pkg.name));
|
|
33
37
|
await shell.publishPlaceholder(pkg, { NPM_CONFIG_OTP: otp });
|
|
34
38
|
}
|
|
39
|
+
await waitForPublishedPackages(shell, missing);
|
|
35
40
|
shell.log('Bootstrap complete. Run smoo release trust-publisher before the first CI publish.');
|
|
36
41
|
return missing;
|
|
37
42
|
}
|
|
43
|
+
async function waitForPublishedPackages(shell, packages) {
|
|
44
|
+
let pending = [...packages];
|
|
45
|
+
for (const delayMs of NPM_BOOTSTRAP_POLL_DELAYS_MS) {
|
|
46
|
+
if (delayMs > 0) {
|
|
47
|
+
await shell.wait(delayMs);
|
|
48
|
+
}
|
|
49
|
+
const visible = await Promise.all(pending.map((pkg) => shell.packageVersionExists(pkg.name, NPM_BOOTSTRAP_VERSION)));
|
|
50
|
+
pending = pending.filter((_, index) => !visible[index]);
|
|
51
|
+
if (pending.length === 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`Bootstrap uploads succeeded, but npm did not expose these packages after ${NPM_BOOTSTRAP_VISIBILITY_TIMEOUT_MS / 1000} seconds: ${pending
|
|
56
|
+
.map((pkg) => pkg.name)
|
|
57
|
+
.join(', ')}. Retry smoo release trust-publisher later; do not bootstrap again.`);
|
|
58
|
+
}
|
|
38
59
|
function selectedReleasePackages(packages, selections) {
|
|
39
60
|
if (selections.length === 0) {
|
|
40
61
|
return packages;
|