diff --git a/.changeset/split-tarballs-from-docs.md b/.changeset/split-tarballs-from-docs.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/split-tarballs-from-docs.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.github/workflows/tarballs-checks.yml b/.github/workflows/tarballs-checks.yml new file mode 100644 index 0000000000..34bed28109 --- /dev/null +++ b/.github/workflows/tarballs-checks.yml @@ -0,0 +1,59 @@ +name: Tarballs Checks + +on: + push: + branches: + - main + tags: + - "!*" + pull_request: + +concurrency: + # Unique group for this workflow and branch + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + tarballs-preview-smoke: + name: Tarballs Preview Smoke Checks + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + deployments: read + env: + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ vars.TURBO_TEAM }} + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v5 + + - name: Setup Node.js 22.x + uses: actions/setup-node@v4 + with: + node-version: 22.x + cache: "pnpm" + + - name: Install Dependencies + run: pnpm install --frozen-lockfile + + - name: Waiting for the Tarballs Vercel deployment + id: waitForTarballsDeployment + uses: ./.github/actions/wait-for-vercel-project + with: + project-slug: workflow-tarballs + timeout: 1000 + check-interval: 15 + environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'preview' }} + + - name: Verify tarball endpoints + # The tarballs project must be publicly accessible (no Deployment + # Protection) so that pnpm/npm can install from preview URLs. + # The smoke checks make unauthenticated requests and fail loudly + # if a login redirect or non-2xx response is returned. + run: pnpm --filter tarballs test:smoke + env: + DEPLOYMENT_URL: ${{ steps.waitForTarballsDeployment.outputs.deployment-url }} diff --git a/docs/.gitignore b/docs/.gitignore index 0805f529d5..a23daf7601 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -33,6 +33,4 @@ next-env.d.ts # pagefind _pagefind/ -# tarballs -*.tgz .env*.local diff --git a/docs/app/[lang]/(home)/components/preview-badge.tsx b/docs/app/[lang]/(home)/components/preview-badge.tsx index 204c2735d3..24085ef2b9 100644 --- a/docs/app/[lang]/(home)/components/preview-badge.tsx +++ b/docs/app/[lang]/(home)/components/preview-badge.tsx @@ -16,6 +16,7 @@ import { type PreviewBadgeProps = { deploymentUrl: string; + tarballsUrl: string; }; function CopyButton({ text }: { text: string }) { @@ -65,8 +66,8 @@ function CopyButton({ text }: { text: string }) { ); } -export function PreviewBadge({ deploymentUrl }: PreviewBadgeProps) { - const baseUrl = deploymentUrl.replace(/\/$/, ''); +export function PreviewBadge({ deploymentUrl, tarballsUrl }: PreviewBadgeProps) { + const baseUrl = (tarballsUrl || deploymentUrl).replace(/\/$/, ''); const installCmd = `pnpm i ${baseUrl}/workflow.tgz`; const npxCmd = `npx workflow@${baseUrl}/workflow.tgz web`; diff --git a/docs/app/[lang]/(home)/page.tsx b/docs/app/[lang]/(home)/page.tsx index cd10b1e800..b371745f11 100644 --- a/docs/app/[lang]/(home)/page.tsx +++ b/docs/app/[lang]/(home)/page.tsx @@ -31,6 +31,9 @@ const isPreview = process.env.VERCEL_ENV === 'preview'; const deploymentUrl = process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : ''; +const tarballsUrl = process.env.TARBALLS_URL + ? `https://${process.env.TARBALLS_URL}` + : ''; const Home = () => (
@@ -38,7 +41,7 @@ const Home = () => ( {isPreview && deploymentUrl && (
- +
)}
diff --git a/docs/package.json b/docs/package.json index 3879797b6e..bd0bdda740 100644 --- a/docs/package.json +++ b/docs/package.json @@ -8,7 +8,6 @@ "dev": "next dev --turbo", "start": "next start", "postinstall": "fumadocs-mdx", - "prebuild": "node scripts/pack.ts", "lint": "biome check", "lint:links": "bun ./scripts/lint.ts", "format": "biome format --write", diff --git a/docs/proxy.ts b/docs/proxy.ts index a2b7d5185e..b6be88c65d 100644 --- a/docs/proxy.ts +++ b/docs/proxy.ts @@ -132,7 +132,7 @@ const proxy = (request: NextRequest, context: NextFetchEvent) => { export const config = { // Matcher ignoring `/_next/`, `/api/`, static assets, favicon, sitemap, robots, etc. matcher: [ - '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|og|.*\\.tgz$|.*\\.svg$|.*\\.zip$).*)', + '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|og|.*\\.svg$|.*\\.zip$).*)', ], }; diff --git a/docs/scripts/check-docs-smoke.mjs b/docs/scripts/check-docs-smoke.mjs index 49175d4dcd..3142ee70f6 100644 --- a/docs/scripts/check-docs-smoke.mjs +++ b/docs/scripts/check-docs-smoke.mjs @@ -246,37 +246,8 @@ const checks = [ name: 'Sitemap', run: () => assertXmlResponse('/sitemap.xml'), }, - { - name: 'Tarball - workflow', - run: () => assertTgzResponse('/workflow.tgz'), - }, - { - name: 'Tarball - workflow-core', - run: () => assertTgzResponse('/workflow-core.tgz'), - }, - { - name: 'Tarball - workflow-next', - run: () => assertTgzResponse('/workflow-next.tgz'), - }, ]; -const GZIP_SIGNATURE = [0x1f, 0x8b]; - -const assertTgzResponse = async (path) => { - const res = await fetch(`${BASE_URL}${path}`, { - headers: await getTrustedSourcesHeaders(), - }); - if (!res.ok) { - throw new Error(`${path} returned ${res.status}`); - } - const buf = new Uint8Array(await res.arrayBuffer()); - for (let i = 0; i < GZIP_SIGNATURE.length; i += 1) { - if (buf[i] !== GZIP_SIGNATURE[i]) { - throw new Error(`${path} did not start with gzip signature bytes`); - } - } -}; - const assertXmlResponse = async (path) => { const res = await fetch(`${BASE_URL}${path}`, { headers: await getTrustedSourcesHeaders(), diff --git a/docs/scripts/pack.ts b/docs/scripts/pack.ts deleted file mode 100644 index a3895ae0ba..0000000000 --- a/docs/scripts/pack.ts +++ /dev/null @@ -1,120 +0,0 @@ -import cp from 'node:child_process'; -import fs from 'node:fs/promises'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { promisify } from 'node:util'; - -const exec = promisify(cp.exec); - -interface PackageJson { - name: string; - version: string; - private?: boolean; - dependencies?: Record; - devDependencies?: Record; - peerDependencies?: Record; -} - -const rootDir = fileURLToPath(new URL('../../', import.meta.url)); -const packagesDir = path.join(rootDir, 'packages'); -const outDir = fileURLToPath(new URL('../public', import.meta.url)); - -async function main() { - const sha = await getSha(); - - // Ensure output directory exists - await fs.mkdir(outDir, { recursive: true }); - - // Scan the packages directory for all packages - const packageDirs = await fs.readdir(packagesDir); - const packages: Array<{ - name: string; - dir: string; - packageJson: PackageJson; - }> = []; - - for (const packageDir of packageDirs) { - const dir = path.join(packagesDir, packageDir); - const packageJsonPath = path.join(dir, 'package.json'); - - try { - const stat = await fs.stat(packageJsonPath); - if (!stat.isFile()) continue; - } catch { - continue; // Skip directories without package.json - } - - const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8'); - const packageJson: PackageJson = JSON.parse(packageJsonContent); - - // Skip private packages - if (packageJson.private) continue; - - packages.push({ name: packageJson.name, dir, packageJson }); - } - - // Create a set of all package names for dependency resolution - const packageNames = new Set(packages.map((p) => p.name)); - - for (const { name, dir, packageJson } of packages) { - const packageJsonPath = path.join(dir, 'package.json'); - const originalPackageJson = JSON.stringify(packageJson, null, 2); - - // Create modified package.json with preview version - const modifiedPackageJson: PackageJson = JSON.parse(originalPackageJson); - modifiedPackageJson.version += `-${sha}`; - - // Update workspace dependencies to use preview tarball URLs - const updateDeps = (deps: Record | undefined) => { - if (!deps) return; - for (const depName of Object.keys(deps)) { - if (packageNames.has(depName)) { - const escapedName = depName.replace(/^@(.+)\//, '$1-'); - deps[depName] = - `https://${process.env.VERCEL_URL}/${escapedName}.tgz`; - } - } - }; - - updateDeps(modifiedPackageJson.dependencies); - updateDeps(modifiedPackageJson.devDependencies); - updateDeps(modifiedPackageJson.peerDependencies); - - // Write modified package.json - await fs.writeFile( - packageJsonPath, - JSON.stringify(modifiedPackageJson, null, 2) - ); - - try { - // Pack the package - await exec(`pnpm pack --out="${outDir}/%s.tgz"`, { cwd: dir }); - console.log(`Packed ${name}`); - } finally { - // Always restore original package.json - await fs.writeFile(packageJsonPath, originalPackageJson); - } - } - - console.log( - `\nSuccessfully packed ${packages.length} preview packages to ${outDir}` - ); -} - -async function getSha(): Promise { - try { - const { stdout } = await exec('git rev-parse --short HEAD', { - cwd: rootDir, - }); - return stdout.trim(); - } catch (error) { - console.error('Failed to get git SHA:', error); - console.log('Using "local" as the SHA.'); - return 'local'; - } -} - -main().catch((err) => { - console.error('Error running pack:', err); - process.exit(1); -}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7b9b92fd3f..05e3c20aef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1496,6 +1496,87 @@ importers: specifier: 'catalog:' version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.0)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.3) + tarballs: + dependencies: + '@workflow/ai': + specifier: workspace:* + version: link:../packages/ai + '@workflow/astro': + specifier: workspace:* + version: link:../packages/astro + '@workflow/builders': + specifier: workspace:* + version: link:../packages/builders + '@workflow/cli': + specifier: workspace:* + version: link:../packages/cli + '@workflow/core': + specifier: workspace:* + version: link:../packages/core + '@workflow/errors': + specifier: workspace:* + version: link:../packages/errors + '@workflow/nest': + specifier: workspace:* + version: link:../packages/nest + '@workflow/next': + specifier: workspace:* + version: link:../packages/next + '@workflow/nitro': + specifier: workspace:* + version: link:../packages/nitro + '@workflow/nuxt': + specifier: workspace:* + version: link:../packages/nuxt + '@workflow/rollup': + specifier: workspace:* + version: link:../packages/rollup + '@workflow/serde': + specifier: workspace:* + version: link:../packages/serde + '@workflow/sveltekit': + specifier: workspace:* + version: link:../packages/sveltekit + '@workflow/swc-plugin': + specifier: workspace:* + version: link:../packages/swc-plugin-workflow + '@workflow/typescript-plugin': + specifier: workspace:* + version: link:../packages/typescript-plugin + '@workflow/utils': + specifier: workspace:* + version: link:../packages/utils + '@workflow/vite': + specifier: workspace:* + version: link:../packages/vite + '@workflow/vitest': + specifier: workspace:* + version: link:../packages/vitest + '@workflow/web': + specifier: workspace:* + version: link:../packages/web + '@workflow/web-shared': + specifier: workspace:* + version: link:../packages/web-shared + '@workflow/world': + specifier: workspace:* + version: link:../packages/world + '@workflow/world-local': + specifier: workspace:* + version: link:../packages/world-local + '@workflow/world-postgres': + specifier: workspace:* + version: link:../packages/world-postgres + '@workflow/world-testing': + specifier: workspace:* + version: link:../packages/world-testing + '@workflow/world-vercel': + specifier: workspace:* + version: link:../packages/world-vercel + workflow: + specifier: workspace:* + version: link:../packages/workflow + workbench/astro: dependencies: '@astrojs/node': @@ -2744,24 +2825,28 @@ packages: engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [musl] '@biomejs/cli-linux-arm64@2.4.4': resolution: {integrity: sha512-V/NFfbWhsUU6w+m5WYbBenlEAz8eYnSqRMDMAW3K+3v0tYVkNyZn8VU0XPxk/lOqNXLSCCrV7FmV/u3SjCBShg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + libc: [glibc] '@biomejs/cli-linux-x64-musl@2.4.4': resolution: {integrity: sha512-gGvFTGpOIQDb5CQ2VC0n9Z2UEqlP46c4aNgHmAMytYieTGEcfqhfCFnhs6xjt0S3igE6q5GLuIXtdQt3Izok+g==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [musl] '@biomejs/cli-linux-x64@2.4.4': resolution: {integrity: sha512-R4+ZCDtG9kHArasyBO+UBD6jr/FcFCTH8QkNTOCu0pRJzCWyWC4EtZa2AmUZB5h3e0jD7bRV2KvrENcf8rndBg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + libc: [glibc] '@biomejs/cli-win32-arm64@2.4.4': resolution: {integrity: sha512-trzCqM7x+Gn832zZHgr28JoYagQNX4CZkUZhMUac2YxvvyDRLJDrb5m9IA7CaZLlX6lTQmADVfLEKP1et1Ma4Q==} @@ -4041,166 +4126,196 @@ packages: resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm64@1.2.4': resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.3': resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.3': resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.3': resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.3': resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.3': resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.3': resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.34.4': resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.34.4': resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-ppc64@0.34.4': resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.34.4': resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.34.4': resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.4': resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.34.4': resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.34.4': resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==} @@ -4538,42 +4653,49 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-arm64-musl@1.1.1': resolution: {integrity: sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@napi-rs/nice-linux-ppc64-gnu@1.1.1': resolution: {integrity: sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==} engines: {node: '>= 10'} cpu: [ppc64] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-riscv64-gnu@1.1.1': resolution: {integrity: sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-s390x-gnu@1.1.1': resolution: {integrity: sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==} engines: {node: '>= 10'} cpu: [s390x] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-x64-gnu@1.1.1': resolution: {integrity: sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@napi-rs/nice-linux-x64-musl@1.1.1': resolution: {integrity: sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@napi-rs/nice-openharmony-arm64@1.1.1': resolution: {integrity: sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==} @@ -4703,24 +4825,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@next/swc-linux-arm64-musl@16.2.1': resolution: {integrity: sha512-ssKq6iMRnHdnycGp9hCuGnXJZ0YPr4/wNwrfE5DbmvEcgl9+yv97/Kq3TPVDfYome1SW5geciLB9aiEqKXQjlQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@next/swc-linux-x64-gnu@16.2.1': resolution: {integrity: sha512-HQm7SrHRELJ30T1TSmT706IWovFFSRGxfgUkyWJZF/RKBMdbdRWJuFrcpDdE5vy9UXjFOx6L3mRdqH04Mmx0hg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@next/swc-linux-x64-musl@16.2.1': resolution: {integrity: sha512-aV2iUaC/5HGEpbBkE+4B8aHIudoOy5DYekAKOMSHoIYQ66y/wIVeaRx8MS2ZMdxe/HIXlMho4ubdZs/J8441Tg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@next/swc-win32-arm64-msvc@16.2.1': resolution: {integrity: sha512-IXdNgiDHaSk0ZUJ+xp0OQTdTgnpx1RCfRTalhn3cjOP+IddTMINwA7DXZrwTmGDO8SUr5q2hdP/du4DcrB1GxA==} @@ -4775,24 +4901,28 @@ packages: engines: {node: '>= 12'} cpu: [arm64] os: [linux] + libc: [glibc] '@node-rs/xxhash-linux-arm64-musl@1.7.6': resolution: {integrity: sha512-AB5m6crGYSllM9F/xZNOQSPImotR5lOa9e4arW99Bv82S+gcpphI8fGMDOVTTCXY/RLRhvvhwzLDxmLB2O8VDg==} engines: {node: '>= 12'} cpu: [arm64] os: [linux] + libc: [musl] '@node-rs/xxhash-linux-x64-gnu@1.7.6': resolution: {integrity: sha512-a2A6M+5tc0PVlJlE/nl0XsLEzMpKkwg7Y1lR5urFUbW9uVQnKjJYQDrUojhlXk0Uv3VnYQPa6ThmwlacZA5mvQ==} engines: {node: '>= 12'} cpu: [x64] os: [linux] + libc: [glibc] '@node-rs/xxhash-linux-x64-musl@1.7.6': resolution: {integrity: sha512-WioGJSC1GoxQpmdQrG5l/uddSBAS4XCWczHNwXe895J5xadGQzyvmr0r17BNfihvbBUDH1H9jwouNYzDDeA6+A==} engines: {node: '>= 12'} cpu: [x64] os: [linux] + libc: [musl] '@node-rs/xxhash-wasm32-wasi@1.7.6': resolution: {integrity: sha512-WDXXKMMFMrez+esm2DzMPHFNPFYf+wQUtaXrXwtxXeQMFEzleOLwEaqV0+bbXGJTwhPouL3zY1Qo2xmIH4kkTg==} @@ -5139,84 +5269,98 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-arm64-gnu@0.96.0': resolution: {integrity: sha512-Yl+KcTldsEJNcaYxxonwAXZ2q3gxIzn3kXYQWgKWdaGIpNhOCWqF+KE5WLsldoh5Ro5SHtomvb8GM6cXrIBMog==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-arm64-musl@0.117.0': resolution: {integrity: sha512-C3zapJconWpl2Y7LR3GkRkH6jxpuV2iVUfkFcHT5Ffn4Zu7l88mZa2dhcfdULZDybN1Phka/P34YUzuskUUrXw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-minify/binding-linux-arm64-musl@0.96.0': resolution: {integrity: sha512-rNqoFWOWaxwMmUY5fspd/h5HfvgUlA3sv9CUdA2MpnHFiyoJNovR7WU8tGh+Yn0qOAs0SNH0a05gIthHig14IA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-minify/binding-linux-ppc64-gnu@0.117.0': resolution: {integrity: sha512-2T/Bm+3/qTfuNS4gKSzL8qbiYk+ErHW2122CtDx+ilZAzvWcJ8IbqdZIbEWOlwwe03lESTxPwTBLFqVgQU2OeQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-riscv64-gnu@0.117.0': resolution: {integrity: sha512-MKLjpldYkeoB4T+yAi4aIAb0waifxUjLcKkCUDmYAY3RqBJTvWK34KtfaKZL0IBMIXfD92CbKkcxQirDUS9Xcg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-riscv64-gnu@0.96.0': resolution: {integrity: sha512-3paajIuzGnukHwSI3YBjYVqbd72pZd8NJxaayaNFR0AByIm8rmIT5RqFXbq8j2uhtpmNdZRXiu0em1zOmIScWA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-riscv64-musl@0.117.0': resolution: {integrity: sha512-UFVcbPvKUStry6JffriobBp8BHtjmLLPl4bCY+JMxIn/Q3pykCpZzRwFTcDurG/kY8tm+uSNfKKdRNa5Nh9A7g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-minify/binding-linux-s390x-gnu@0.117.0': resolution: {integrity: sha512-B9GyPQ1NKbvpETVAMyJMfRlD3c6UJ7kiuFUAlx9LTYiQL+YIyT6vpuRlq1zgsXxavZluVrfeJv6x0owV4KDx4Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-s390x-gnu@0.96.0': resolution: {integrity: sha512-9ESrpkB2XG0lQ89JlsxlZa86iQCOs+jkDZLl6O+u5wb7ynUy21bpJJ1joauCOSYIOUlSy3+LbtJLiqi7oSQt5Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-x64-gnu@0.117.0': resolution: {integrity: sha512-fXfhtr+WWBGNy4M5GjAF5vu/lpulR4Me34FjTyaK9nDrTZs7LM595UDsP1wliksqp4hD/KdoqHGmbCrC+6d4vA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-x64-gnu@0.96.0': resolution: {integrity: sha512-UMM1jkns+p+WwwmdjC5giI3SfR2BCTga18x3C0cAu6vDVf4W37uTZeTtSIGmwatTBbgiq++Te24/DE0oCdm1iQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-x64-musl@0.117.0': resolution: {integrity: sha512-jFBgGbx1oLadb83ntJmy1dWlAHSQanXTS21G4PgkxyONmxZdZ/UMKr7KsADzMuoPsd2YhJHxzRpwJd9U+4BFBw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-minify/binding-linux-x64-musl@0.96.0': resolution: {integrity: sha512-8b1naiC7MdP7xeMi7cQ5tb9W1rZAP9Qz/jBRqp1Y5EOZ1yhSGnf1QWuZ/0pCc+XiB9vEHXEY3Aki/H+86m2eOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-minify/binding-openharmony-arm64@0.117.0': resolution: {integrity: sha512-nxPd9vx1vYz8IlIMdl9HFdOK/ood1H5hzbSFsyO8JU55tkcJoBL8TLCbuFf9pHpOy27l2gcPyV6z3p4eAcTH5Q==} @@ -5311,48 +5455,56 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-arm64-musl@0.117.0': resolution: {integrity: sha512-QagKTDF4lrz8bCXbUi39Uq5xs7C7itAseKm51f33U+Dyar9eJY/zGKqfME9mKLOiahX7Fc1J3xMWVS0AdDXLPg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-parser/binding-linux-ppc64-gnu@0.117.0': resolution: {integrity: sha512-RPddpcE/0xxWaommWy0c5i/JdrXcXAkxBS2GOrAUh5LKmyCh03hpJedOAWszG4ADsKQwoUQQ1/tZVGRhZIWtKA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-riscv64-gnu@0.117.0': resolution: {integrity: sha512-ur/WVZF9FSOiZGxyP+nfxZzuv6r5OJDYoVxJnUR7fM/hhXLh4V/be6rjbzm9KLCDBRwYCEKJtt+XXNccwd06IA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-riscv64-musl@0.117.0': resolution: {integrity: sha512-ujGcAx8xAMvhy7X5sBFi3GXML1EtyORuJZ5z2T6UV3U416WgDX/4OCi3GnoteeenvxIf6JgP45B+YTHpt71vpA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-parser/binding-linux-s390x-gnu@0.117.0': resolution: {integrity: sha512-hbsfKjUwRjcMZZvvmpZSc+qS0bHcHRu8aV/I3Ikn9BzOA0ZAgUE7ctPtce5zCU7bM8dnTLi4sJ1Pi9YHdx6Urw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-x64-gnu@0.117.0': resolution: {integrity: sha512-1QrTrf8rige7UPJrYuDKJLQOuJlgkt+nRSJLBMHWNm9TdivzP48HaK3f4q18EjNlglKtn03lgjMu4fryDm8X4A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-x64-musl@0.117.0': resolution: {integrity: sha512-gRvK6HPzF5ITRL68fqb2WYYs/hGviPIbkV84HWCgiJX+LkaOpp+HIHQl3zVZdyKHwopXToTbXbtx/oFjDjl8pg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-parser/binding-openharmony-arm64@0.117.0': resolution: {integrity: sha512-QPJvFbnnDZZY7xc+xpbIBWLThcGBakwaYA9vKV8b3+oS5MGfAZUoTFJcix5+Zg2Ri46sOfrUim6Y6jsKNcssAQ==} @@ -5469,84 +5621,98 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-arm64-gnu@0.96.0': resolution: {integrity: sha512-kaqvUzNu8LL4aBSXqcqGVLFG13GmJEplRI2+yqzkgAItxoP/LfFMdEIErlTWLGyBwd0OLiNMHrOvkcCQRWadVg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-arm64-musl@0.117.0': resolution: {integrity: sha512-ykxpPQp0eAcSmhy0Y3qKvdanHY4d8THPonDfmCoktUXb6r0X6qnjpJB3V+taN1wevW55bOEZd97kxtjTKjqhmg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-transform/binding-linux-arm64-musl@0.96.0': resolution: {integrity: sha512-EiG/L3wEkPgTm4p906ufptyblBgtiQWTubGg/JEw82f8uLRroayr5zhbUqx40EgH037a3SfJthIyLZi7XPRFJw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-transform/binding-linux-ppc64-gnu@0.117.0': resolution: {integrity: sha512-Rvspti4Kr7eq6zSrURK5WjscfWQPvmy/KjJZV45neRKW8RLonE3r9+NgrwSLGoHvQ3F24fbqlkplox1RtlhH5A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-riscv64-gnu@0.117.0': resolution: {integrity: sha512-Dr2ZW9ZZ4l1eQ5JUEUY3smBh4JFPCPuybWaDZTLn3ADZjyd8ZtNXEjeMT8rQbbhbgSL9hEgbwaqraole3FNThQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-riscv64-gnu@0.96.0': resolution: {integrity: sha512-r01CY6OxKGtVeYnvH4mGmtkQMlLkXdPWWNXwo5o7fE2s/fgZPMpqh8bAuXEhuMXipZRJrjxTk1+ZQ4KCHpMn3Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-riscv64-musl@0.117.0': resolution: {integrity: sha512-oD1Bnes1bIC3LVBSrWEoSUBj6fvatESPwAVWfJVGVQlqWuOs/ZBn1e4Nmbipo3KGPHK7DJY75r/j7CQCxhrOFQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-transform/binding-linux-s390x-gnu@0.117.0': resolution: {integrity: sha512-qT//IAPLvse844t99Kff5j055qEbXfwzWgvCMb0FyjisnB8foy25iHZxZIocNBe6qwrCYWUP1M8rNrB/WyfS1Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-s390x-gnu@0.96.0': resolution: {integrity: sha512-4djg2vYLGbVeS8YiA2K4RPPpZE4fxTGCX5g/bOMbCYyirDbmBAIop4eOAj8vOA9i1CcWbDtmp+PVJ1dSw7f3IQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-x64-gnu@0.117.0': resolution: {integrity: sha512-2YEO5X+KgNzFqRVO5dAkhjcI5gwxus4NSWVl/+cs2sI6P0MNPjqE3VWPawl4RTC11LvetiiZdHcujUCPM8aaUw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-x64-gnu@0.96.0': resolution: {integrity: sha512-f6pcWVz57Y8jXa2OS7cz3aRNuks34Q3j61+3nQ4xTE8H1KbalcEvHNmM92OEddaJ8QLs9YcE0kUC6eDTbY34+A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-x64-musl@0.117.0': resolution: {integrity: sha512-3wqWbTSaIFZvDr1aqmTul4cg8PRWYh6VC52E8bLI7ytgS/BwJLW+sDUU2YaGIds4sAf/1yKeJRmudRCDPW9INg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-transform/binding-linux-x64-musl@0.96.0': resolution: {integrity: sha512-NSiRtFvR7Pbhv3mWyPMkTK38czIjcnK0+K5STo3CuzZRVbX1TM17zGdHzKBUHZu7v6IQ6/XsQ3ELa1BlEHPGWQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-transform/binding-openharmony-arm64@0.117.0': resolution: {integrity: sha512-Ebxx6NPqhzlrjvx4+PdSqbOq+li0f7X59XtJljDghkbJsbnkHvhLmPR09ifHt5X32UlZN63ekjwcg/nbmHLLlA==} @@ -5623,36 +5789,42 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.1': resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.1': resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.1': resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.1': resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.1': resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [musl] '@parcel/watcher-wasm@2.5.1': resolution: {integrity: sha512-RJxlQQLkaMMIuWRozy+z2vEqbaQlCuaCgVZIUCzQLYggY22LZbP5Y1+ia+FD724Ids9e+XIyOLXLrLgQSHIthw==} @@ -7026,121 +7198,145 @@ packages: resolution: {integrity: sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-gnueabihf@4.60.0': resolution: {integrity: sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.53.2': resolution: {integrity: sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm-musleabihf@4.60.0': resolution: {integrity: sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.53.2': resolution: {integrity: sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-gnu@4.60.0': resolution: {integrity: sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.53.2': resolution: {integrity: sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-musl@4.60.0': resolution: {integrity: sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.53.2': resolution: {integrity: sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-gnu@4.60.0': resolution: {integrity: sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.60.0': resolution: {integrity: sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.53.2': resolution: {integrity: sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-gnu@4.60.0': resolution: {integrity: sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.60.0': resolution: {integrity: sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.53.2': resolution: {integrity: sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.60.0': resolution: {integrity: sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.53.2': resolution: {integrity: sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-musl@4.60.0': resolution: {integrity: sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.53.2': resolution: {integrity: sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-s390x-gnu@4.60.0': resolution: {integrity: sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.53.2': resolution: {integrity: sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.60.0': resolution: {integrity: sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.53.2': resolution: {integrity: sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-linux-x64-musl@4.60.0': resolution: {integrity: sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.60.0': resolution: {integrity: sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==} @@ -7580,24 +7776,28 @@ packages: engines: {node: '>=10'} cpu: [arm64] os: [linux] + libc: [glibc] '@swc/core-linux-arm64-musl@1.15.3': resolution: {integrity: sha512-j4SJniZ/qaZ5g8op+p1G9K1z22s/EYGg1UXIb3+Cg4nsxEpF5uSIGEE4mHUfA70L0BR9wKT2QF/zv3vkhfpX4g==} engines: {node: '>=10'} cpu: [arm64] os: [linux] + libc: [musl] '@swc/core-linux-x64-gnu@1.15.3': resolution: {integrity: sha512-aKttAZnz8YB1VJwPQZtyU8Uk0BfMP63iDMkvjhJzRZVgySmqt/apWSdnoIcZlUoGheBrcqbMC17GGUmur7OT5A==} engines: {node: '>=10'} cpu: [x64] os: [linux] + libc: [glibc] '@swc/core-linux-x64-musl@1.15.3': resolution: {integrity: sha512-oe8FctPu1gnUsdtGJRO2rvOUIkkIIaHqsO9xxN0bTR7dFTlPTGi2Fhk1tnvXeyAvCPxLIcwD8phzKg6wLv9yug==} engines: {node: '>=10'} cpu: [x64] os: [linux] + libc: [musl] '@swc/core-win32-arm64-msvc@1.15.3': resolution: {integrity: sha512-L9AjzP2ZQ/Xh58e0lTRMLvEDrcJpR7GwZqAtIeNLcTK7JVE+QineSyHp0kLkO1rttCHyCy0U74kDTj0dRz6raA==} @@ -7710,48 +7910,56 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.1.13': resolution: {integrity: sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-arm64-musl@4.1.18': resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.1.13': resolution: {integrity: sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-x64-gnu@4.1.18': resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.1.13': resolution: {integrity: sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-x64-musl@4.1.18': resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.1.13': resolution: {integrity: sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==} @@ -11530,48 +11738,56 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-gnu@1.30.2: resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.30.1: resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.30.1: resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.30.1: resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.30.1: resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4bc99bd843..da247a5136 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,6 +3,7 @@ packages: - "!workbench/nitro" - packages/* - docs + - tarballs catalog: "@biomejs/biome": ^2.4.4 diff --git a/tarballs/.gitignore b/tarballs/.gitignore new file mode 100644 index 0000000000..da90934723 --- /dev/null +++ b/tarballs/.gitignore @@ -0,0 +1,7 @@ +node_modules +.vercel +.env*.local + +# Generated tarballs and index page +public/*.tgz +public/index.html diff --git a/tarballs/README.md b/tarballs/README.md new file mode 100644 index 0000000000..bde629d9a1 --- /dev/null +++ b/tarballs/README.md @@ -0,0 +1,25 @@ +# tarballs + +Static Vercel project that builds and serves preview tarballs for every public package in `packages/*`. + +For each public package, `scripts/pack.ts`: + +1. Rewrites the package version to `-` and rewrites every workspace dependency to a tarball URL on the current Vercel deployment (`https://$VERCEL_URL/.tgz`). +2. Runs `pnpm pack` and writes the result to `public/.tgz`. +3. Restores the original `package.json`. + +It also generates a `public/index.html` that lists every published package alongside a copyable `pnpm i …` command, so the bare deployment URL is itself useful when shared. + +The deployment serves the resulting `*.tgz` files at the root of the project URL — e.g. `https://.vercel.sh/workflow.tgz`. + +This is used for pre-release testing of `vercel/workflow` PRs by installing tarballs directly: + +```json +{ + "dependencies": { + "workflow": "https://.vercel.sh/workflow.tgz" + } +} +``` + +The Vercel project must be configured to be **publicly accessible** (no Deployment Protection on previews or production) so that `pnpm`/`npm` can fetch tarball URLs from third-party projects. The smoke check (`scripts/check-tarballs-smoke.mjs`) verifies this on every deployment and fails loudly if the deployment is behind a login redirect. diff --git a/tarballs/package.json b/tarballs/package.json new file mode 100644 index 0000000000..44c80990ea --- /dev/null +++ b/tarballs/package.json @@ -0,0 +1,39 @@ +{ + "name": "tarballs", + "version": "0.0.0", + "private": true, + "type": "module", + "license": "Apache-2.0", + "scripts": { + "build": "node scripts/pack.ts", + "test:smoke": "node ./scripts/check-tarballs-smoke.mjs" + }, + "dependencies": { + "@workflow/ai": "workspace:*", + "@workflow/astro": "workspace:*", + "@workflow/builders": "workspace:*", + "@workflow/cli": "workspace:*", + "@workflow/core": "workspace:*", + "@workflow/errors": "workspace:*", + "@workflow/nest": "workspace:*", + "@workflow/next": "workspace:*", + "@workflow/nitro": "workspace:*", + "@workflow/nuxt": "workspace:*", + "@workflow/rollup": "workspace:*", + "@workflow/serde": "workspace:*", + "@workflow/sveltekit": "workspace:*", + "@workflow/swc-plugin": "workspace:*", + "@workflow/typescript-plugin": "workspace:*", + "@workflow/utils": "workspace:*", + "@workflow/vite": "workspace:*", + "@workflow/vitest": "workspace:*", + "@workflow/web": "workspace:*", + "@workflow/web-shared": "workspace:*", + "@workflow/world": "workspace:*", + "@workflow/world-local": "workspace:*", + "@workflow/world-postgres": "workspace:*", + "@workflow/world-testing": "workspace:*", + "@workflow/world-vercel": "workspace:*", + "workflow": "workspace:*" + } +} diff --git a/tarballs/scripts/check-tarballs-smoke.mjs b/tarballs/scripts/check-tarballs-smoke.mjs new file mode 100644 index 0000000000..cc84ae378b --- /dev/null +++ b/tarballs/scripts/check-tarballs-smoke.mjs @@ -0,0 +1,96 @@ +/** + * Tarballs smoke checks. + * + * Validates that the deployed tarballs project is publicly accessible + * (no Vercel Deployment Protection) and serving the expected `*.tgz` + * files with a valid gzip signature. The project must be publicly + * reachable for `pnpm install` to fetch tarball URLs from a third-party + * project, so the smoke checks make no attempt to send a bypass token — + * if a check fails behind a login redirect, the project is misconfigured. + * + * Requires DEPLOYMENT_URL to point at the tarballs deployment. + */ + +const rawBaseUrl = process.env.DEPLOYMENT_URL || ''; +if (!rawBaseUrl) { + console.error('DEPLOYMENT_URL is required'); + process.exit(1); +} +const BASE_URL = rawBaseUrl.startsWith('http') + ? rawBaseUrl + : `https://${rawBaseUrl}`; + +const GZIP_SIGNATURE = [0x1f, 0x8b]; + +const assertNoProtection = async (path) => { + const res = await fetch(`${BASE_URL}${path}`, { redirect: 'manual' }); + const location = res.headers.get('location') || ''; + if ( + res.status === 307 && + (location.includes('vercel.com/login') || + location.includes('/_vercel/login')) + ) { + throw new Error( + `${path} redirected to Vercel login — the tarballs project must be publicly accessible (disable Deployment Protection)` + ); + } +}; + +const assertTgzResponse = async (path) => { + const res = await fetch(`${BASE_URL}${path}`); + if (!res.ok) { + throw new Error(`${path} returned ${res.status}`); + } + const buf = new Uint8Array(await res.arrayBuffer()); + for (let i = 0; i < GZIP_SIGNATURE.length; i += 1) { + if (buf[i] !== GZIP_SIGNATURE[i]) { + throw new Error(`${path} did not start with gzip signature bytes`); + } + } +}; + +const assertHtmlResponse = async (path) => { + const res = await fetch(`${BASE_URL}${path}`); + if (!res.ok) { + throw new Error(`${path} returned ${res.status}`); + } + const contentType = res.headers.get('content-type') || ''; + if (!contentType.includes('text/html')) { + throw new Error(`${path} content-type was ${contentType}`); + } +}; + +const checks = [ + { + name: 'Deployment protection', + run: () => assertNoProtection('/workflow.tgz'), + }, + { + name: 'Index page', + run: () => assertHtmlResponse('/'), + }, + { + name: 'Tarball - workflow', + run: () => assertTgzResponse('/workflow.tgz'), + }, + { + name: 'Tarball - workflow-core', + run: () => assertTgzResponse('/workflow-core.tgz'), + }, + { + name: 'Tarball - workflow-next', + run: () => assertTgzResponse('/workflow-next.tgz'), + }, +]; + +const run = async () => { + for (const check of checks) { + console.log(`Running tarballs smoke check: ${check.name}`); + await check.run(); + } +}; + +run().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/tarballs/scripts/pack.ts b/tarballs/scripts/pack.ts new file mode 100644 index 0000000000..1bf281a703 --- /dev/null +++ b/tarballs/scripts/pack.ts @@ -0,0 +1,221 @@ +import cp from 'node:child_process'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { promisify } from 'node:util'; + +const exec = promisify(cp.exec); + +interface PackageJson { + name: string; + version: string; + private?: boolean; + dependencies?: Record; + devDependencies?: Record; + peerDependencies?: Record; +} + +const rootDir = fileURLToPath(new URL('../../', import.meta.url)); +const packagesDir = path.join(rootDir, 'packages'); +const outDir = fileURLToPath(new URL('../public', import.meta.url)); + +async function main() { + const sha = await getSha(); + + // Ensure output directory exists + await fs.mkdir(outDir, { recursive: true }); + + // Scan the packages directory for all packages + const packageDirs = await fs.readdir(packagesDir); + const packages: Array<{ + name: string; + dir: string; + packageJson: PackageJson; + originalContent: string; + }> = []; + + for (const packageDir of packageDirs) { + const dir = path.join(packagesDir, packageDir); + const packageJsonPath = path.join(dir, 'package.json'); + + try { + const stat = await fs.stat(packageJsonPath); + if (!stat.isFile()) continue; + } catch { + continue; // Skip directories without package.json + } + + const originalContent = await fs.readFile(packageJsonPath, 'utf8'); + const packageJson: PackageJson = JSON.parse(originalContent); + + // Skip private packages + if (packageJson.private) continue; + + packages.push({ + name: packageJson.name, + dir, + packageJson, + originalContent, + }); + } + + // Create a set of all package names for dependency resolution + const packageNames = new Set(packages.map((p) => p.name)); + + for (const { name, dir, packageJson, originalContent } of packages) { + const packageJsonPath = path.join(dir, 'package.json'); + + // Create modified package.json with preview version + const modifiedPackageJson: PackageJson = JSON.parse( + JSON.stringify(packageJson) + ); + modifiedPackageJson.version += `-${sha}`; + + // Update workspace dependencies to use preview tarball URLs + const updateDeps = (deps: Record | undefined) => { + if (!deps) return; + for (const depName of Object.keys(deps)) { + if (packageNames.has(depName)) { + const escapedName = depName.replace(/^@(.+)\//, '$1-'); + deps[depName] = + `https://${process.env.VERCEL_URL}/${escapedName}.tgz`; + } + } + }; + + updateDeps(modifiedPackageJson.dependencies); + updateDeps(modifiedPackageJson.devDependencies); + updateDeps(modifiedPackageJson.peerDependencies); + + // Write modified package.json + await fs.writeFile( + packageJsonPath, + JSON.stringify(modifiedPackageJson, null, 2) + ); + + try { + // Pack the package + await exec(`pnpm pack --out="${outDir}/%s.tgz"`, { cwd: dir }); + console.log(`Packed ${name}`); + } finally { + // Always restore original package.json (preserves trailing newline / + // exact byte content of the source file) + await fs.writeFile(packageJsonPath, originalContent); + } + } + + await writeIndexHtml(packages.map((p) => p.name).sort(), sha); + + console.log( + `\nSuccessfully packed ${packages.length} preview packages to ${outDir}` + ); +} + +function escapeHtml(value: string): string { + return value + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll("'", '''); +} + +async function writeIndexHtml( + packageNames: string[], + sha: string +): Promise { + // Use the actual deployment URL when running on Vercel, otherwise build + // commands relative to the page so they remain useful when the file is + // viewed via a non-Vercel host or directly from disk. + const baseUrlExpr = process.env.VERCEL_URL + ? `https://${process.env.VERCEL_URL}` + : ''; + + const rows = packageNames + .map((name) => { + const escapedName = name.replace(/^@(.+)\//, '$1-'); + const installCmd = `pnpm i ${baseUrlExpr}/${escapedName}.tgz`; + return ` + ${escapeHtml(name)} + + ${escapeHtml(installCmd)} + + + `; + }) + .join('\n'); + + const html = ` + + + + + Workflow SDK preview tarballs + + + +

Workflow SDK preview tarballs

+

Built from ${escapeHtml(sha)}. Drop one of these install commands into a project to test pre-release builds.

+ + + +${rows} + +
PackageInstall
+ + + +`; + + await fs.writeFile(path.join(outDir, 'index.html'), html); +} + +async function getSha(): Promise { + try { + const { stdout } = await exec('git rev-parse --short HEAD', { + cwd: rootDir, + }); + return stdout.trim(); + } catch (error) { + console.error('Failed to get git SHA:', error); + console.log('Using "local" as the SHA.'); + return 'local'; + } +} + +main().catch((err) => { + console.error('Error running pack:', err); + process.exit(1); +}); diff --git a/tarballs/turbo.json b/tarballs/turbo.json new file mode 100644 index 0000000000..0ad00e728b --- /dev/null +++ b/tarballs/turbo.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://turborepo.org/schema.json", + "extends": ["//"], + "tasks": { + "build": { + "outputs": ["public/*.tgz", "public/index.html"] + } + } +} diff --git a/tarballs/vercel.json b/tarballs/vercel.json new file mode 100644 index 0000000000..88798a2855 --- /dev/null +++ b/tarballs/vercel.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "buildCommand": "pnpm --filter tarballs build", + "installCommand": "pnpm install --frozen-lockfile", + "outputDirectory": "public", + "framework": null +}