From f72ed1e20579ab3247f362d4a44b4abe893254c2 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Mon, 1 Jun 2026 18:59:23 -0400 Subject: [PATCH] fix: own Playground SQLite alias packaging --- package-lock.json | 12 ++++ package.json | 4 ++ packages/runtime-playground/package.json | 1 + .../normalize-playground-sqlite-package.mjs | 68 +++++++++++++++++++ scripts/package-distribution-smoke.ts | 22 +++++- scripts/package-release-artifact.ts | 6 ++ scripts/playground-sqlite-alias-smoke.ts | 29 ++++++++ 7 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 scripts/normalize-playground-sqlite-package.mjs create mode 100644 scripts/playground-sqlite-alias-smoke.ts diff --git a/package-lock.json b/package-lock.json index d3306a4..7d84f93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@chubes4/wp-codebox-core": "file:packages/runtime-core", "@chubes4/wp-codebox-playground": "file:packages/runtime-playground", "@wp-playground/cli": "^3.1.35", + "@wp-playground/wordpress-builds": "^0.9.4", "abort-controller": "^3.0.0", "accepts": "^1.3.8", "aggregate-error": "^3.1.0", @@ -1580,6 +1581,16 @@ "npm": ">=10.2.3" } }, + "node_modules/@wp-playground/wordpress-builds": { + "version": "0.9.19", + "resolved": "https://registry.npmjs.org/@wp-playground/wordpress-builds/-/wordpress-builds-0.9.19.tgz", + "integrity": "sha512-dlqvh/MJDpE5W68vgPPKUjpip6zMuBh59L3D18ZX+pdwurC4q4ydrTww/3sTMV69BBcoH6kF93YtAtujNC5Mpw==", + "license": "GPL-2.0-or-later", + "engines": { + "node": ">=18.18.0", + "npm": ">=8.11.0" + } + }, "node_modules/@zip.js/zip.js": { "version": "2.7.57", "resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.57.tgz", @@ -3818,6 +3829,7 @@ "dependencies": { "@chubes4/wp-codebox-core": "file:../runtime-core", "@wp-playground/cli": "^3.1.35", + "@wp-playground/wordpress-builds": "^0.9.4", "playwright": "^1.60.0" } }, diff --git a/package.json b/package.json index 9390b75..573aee6 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,14 @@ "packages/runtime-playground/package.json", "packages/cli/dist", "packages/cli/package.json", + "scripts/normalize-playground-sqlite-package.mjs", "README.md", "LICENSE" ], "scripts": { "build": "node ./node_modules/typescript/bin/tsc -b packages/runtime-core packages/runtime-playground packages/cli", "prepare": "npm run build", + "postinstall": "node scripts/normalize-playground-sqlite-package.mjs", "package:wordpress-plugin": "tsx scripts/build-wordpress-plugin-zip.ts", "package-distribution-smoke": "tsx scripts/package-distribution-smoke.ts", "release:package": "tsx scripts/package-release-artifact.ts", @@ -79,6 +81,7 @@ "recipe-workspace-seed-excludes-smoke": "tsx scripts/recipe-workspace-seed-excludes-smoke.ts", "recipe-runtime-evidence-smoke": "tsx scripts/recipe-runtime-evidence-smoke.ts", "playground-archive-cache-validation-smoke": "tsx scripts/playground-archive-cache-validation-smoke.ts", + "playground-sqlite-alias-smoke": "tsx scripts/playground-sqlite-alias-smoke.ts", "recipe-playground-boot-failure-smoke": "tsx scripts/recipe-playground-boot-failure-smoke.ts", "runtime-stack-mount-smoke": "tsx scripts/runtime-stack-mount-smoke.ts", "runtime-overlay-php-ai-client-smoke": "tsx scripts/runtime-overlay-php-ai-client-smoke.ts", @@ -108,6 +111,7 @@ "@chubes4/wp-codebox-core": "file:packages/runtime-core", "@chubes4/wp-codebox-playground": "file:packages/runtime-playground", "@wp-playground/cli": "^3.1.35", + "@wp-playground/wordpress-builds": "^0.9.4", "abort-controller": "^3.0.0", "accepts": "^1.3.8", "aggregate-error": "^3.1.0", diff --git a/packages/runtime-playground/package.json b/packages/runtime-playground/package.json index 0816197..2556d14 100644 --- a/packages/runtime-playground/package.json +++ b/packages/runtime-playground/package.json @@ -19,6 +19,7 @@ "dependencies": { "@chubes4/wp-codebox-core": "file:../runtime-core", "@wp-playground/cli": "^3.1.35", + "@wp-playground/wordpress-builds": "^0.9.4", "playwright": "^1.60.0" } } diff --git a/scripts/normalize-playground-sqlite-package.mjs b/scripts/normalize-playground-sqlite-package.mjs new file mode 100644 index 0000000..87a0ff6 --- /dev/null +++ b/scripts/normalize-playground-sqlite-package.mjs @@ -0,0 +1,68 @@ +import { copyFile, mkdir, access } from "node:fs/promises" +import { createRequire } from "node:module" +import { dirname, join } from "node:path" +import { pathToFileURL } from "node:url" + +const rootPackageUrl = pathToFileURL(join(process.cwd(), "package.json")) +const requireFromRoot = createRequire(rootPackageUrl) + +const result = await normalizePlaygroundSqlitePackage(requireFromRoot) + +if (process.env.WP_CODEBOX_PLAYGROUND_SQLITE_ALIAS_DEBUG === "1") { + console.log(JSON.stringify(result)) +} + +export async function normalizePlaygroundSqlitePackage(requireFrom = requireFromRoot) { + const wordpressBuildsRoot = await resolvePackageRoot(requireFrom, "@wp-playground/wordpress-builds") + if (!wordpressBuildsRoot) { + return { status: "skipped", reason: "@wp-playground/wordpress-builds is not installed" } + } + + const sqliteDirectory = join(wordpressBuildsRoot, "src", "sqlite-database-integration") + const target = join(sqliteDirectory, "sqlite-database-integration-trunk.zip") + if (await exists(target)) { + return { status: "present", path: target } + } + + const cliRoot = await resolvePackageRoot(requireFrom, "@wp-playground/cli") + const source = await firstExisting([ + join(sqliteDirectory, "sqlite-database-integration.zip"), + cliRoot ? join(cliRoot, "sqlite-database-integration.zip") : undefined, + ]) + + if (!source) { + return { status: "skipped", reason: "Playground SQLite package source was not found" } + } + + await mkdir(sqliteDirectory, { recursive: true }) + await copyFile(source, target) + + return { status: "created", source, path: target } +} + +async function resolvePackageRoot(requireFrom, packageName) { + try { + return dirname(requireFrom.resolve(`${packageName}/package.json`)) + } catch { + return undefined + } +} + +async function firstExisting(paths) { + for (const path of paths) { + if (path && await exists(path)) { + return path + } + } + + return undefined +} + +async function exists(path) { + try { + await access(path) + return true + } catch { + return false + } +} diff --git a/scripts/package-distribution-smoke.ts b/scripts/package-distribution-smoke.ts index 9d97b57..2546ff0 100644 --- a/scripts/package-distribution-smoke.ts +++ b/scripts/package-distribution-smoke.ts @@ -29,18 +29,30 @@ const { stdout: packStdout } = await execFileAsync( const [pack] = JSON.parse(packStdout) as Array<{ files: Array<{ path: string }>; entryCount: number }> const packedFiles = new Set(pack.files.map((file) => file.path)) +const { stdout: rootPackStdout } = await execFileAsync( + "npm", + ["pack", "--dry-run", "--json"], + { cwd: repoRoot, maxBuffer: 1024 * 1024 * 10 }, +) +const [rootPack] = JSON.parse(rootPackStdout) as Array<{ files: Array<{ path: string }> }> +const rootPackedFiles = new Set(rootPack.files.map((file) => file.path)) + assert.ok(packedFiles.has("package.json"), "CLI package should include package.json") assert.ok(packedFiles.has("README.md"), "CLI package should include README.md") assert.ok(packedFiles.has("dist/index.js"), "CLI package should include compiled binary entrypoint") assert.ok(packedFiles.has("dist/index.d.ts"), "CLI package should include generated types") assert.equal(packedFiles.has("src/index.ts"), false, "CLI package should not ship TypeScript source") assert.ok(pack.entryCount >= 4, "CLI package should contain expected publish files") +assert.ok( + rootPackedFiles.has("scripts/normalize-playground-sqlite-package.mjs"), + "Root package should ship the Playground SQLite package normalizer for clean installs", +) await execFileAsync("npm", ["run", "package:wordpress-plugin"], { cwd: repoRoot, maxBuffer: 1024 * 1024 * 10 }) const pluginZip = resolve(repoRoot, "packages", "wordpress-plugin", "dist", "wp-codebox.zip") await access(pluginZip) -const { stdout: zipStdout } = await execFileAsync("unzip", ["-Z1", pluginZip], { cwd: repoRoot }) +const { stdout: zipStdout } = await execFileAsync("unzip", ["-Z1", pluginZip], { cwd: repoRoot, maxBuffer: 1024 * 1024 * 20 }) const zipEntries = new Set(zipStdout.trim().split("\n").filter(Boolean)) assert.ok(zipEntries.has("wp-codebox/wp-codebox.php"), "Plugin zip should include the main plugin file") @@ -55,6 +67,14 @@ assert.ok( "Plugin zip should include packaged Node runtime for the plugin CLI path", ) assert.ok(zipEntries.has("wp-codebox/vendor/wp-codebox-cli/packages/cli/dist/index.js"), "Plugin zip should include compiled CLI runtime") +assert.ok( + zipEntries.has("wp-codebox/vendor/wp-codebox-cli/node_modules/@wp-playground/wordpress-builds/src/sqlite-database-integration/sqlite-database-integration-trunk.zip"), + "Plugin zip should include Playground's normalized trunk SQLite package alias", +) +assert.ok( + zipEntries.has("wp-codebox/vendor/wp-codebox-cli/scripts/normalize-playground-sqlite-package.mjs"), + "Plugin zip should include the Playground SQLite package normalizer for packaged installs", +) assert.equal(zipEntries.has("wp-codebox/package.json"), false, "Plugin zip should not include package metadata") assert.equal(zipEntries.has("wp-codebox/dist/wp-codebox.zip"), false, "Plugin zip should not include generated artifacts") diff --git a/scripts/package-release-artifact.ts b/scripts/package-release-artifact.ts index 29b37a2..322f62c 100644 --- a/scripts/package-release-artifact.ts +++ b/scripts/package-release-artifact.ts @@ -23,6 +23,8 @@ try { await copyIfPresent("README.md") await copyIfPresent("LICENSE") + await mkdir(join(packageRoot, "scripts"), { recursive: true }) + await cp(resolve(repoRoot, "scripts", "normalize-playground-sqlite-package.mjs"), join(packageRoot, "scripts", "normalize-playground-sqlite-package.mjs")) await cp(resolve(repoRoot, "package.json"), join(packageRoot, "package.json")) await cp(resolve(repoRoot, "package-lock.json"), join(packageRoot, "package-lock.json")) @@ -38,6 +40,10 @@ try { cwd: packageRoot, maxBuffer: 1024 * 1024 * 20, }) + await execFileAsync("node", ["scripts/normalize-playground-sqlite-package.mjs"], { + cwd: packageRoot, + maxBuffer: 1024 * 1024 * 10, + }) await bundleNodeRuntime(packageRoot, platformName, archName) const binDir = join(packageRoot, "bin") diff --git a/scripts/playground-sqlite-alias-smoke.ts b/scripts/playground-sqlite-alias-smoke.ts new file mode 100644 index 0000000..ed319ef --- /dev/null +++ b/scripts/playground-sqlite-alias-smoke.ts @@ -0,0 +1,29 @@ +import assert from "node:assert/strict" +import { createRequire } from "node:module" +import { access, unlink } from "node:fs/promises" +import { dirname, join, resolve } from "node:path" +import { normalizePlaygroundSqlitePackage } from "./normalize-playground-sqlite-package.mjs" + +const repoRoot = resolve(import.meta.dirname, "..") +const requireFromRepo = createRequire(join(repoRoot, "package.json")) +const wordpressBuildsRoot = dirname(requireFromRepo.resolve("@wp-playground/wordpress-builds/package.json")) +const sqliteDirectory = join(wordpressBuildsRoot, "src", "sqlite-database-integration") +const source = join(sqliteDirectory, "sqlite-database-integration.zip") +const target = join(sqliteDirectory, "sqlite-database-integration-trunk.zip") + +await access(source) +await unlink(target).catch((error: NodeJS.ErrnoException) => { + if (error.code !== "ENOENT") { + throw error + } +}) + +const result = await normalizePlaygroundSqlitePackage(requireFromRepo) + +assert.equal(result.status, "created", "Codebox should create Playground's trunk SQLite package alias") +await access(target) + +const existing = await normalizePlaygroundSqlitePackage(requireFromRepo) +assert.equal(existing.status, "present", "Codebox should treat an existing Playground SQLite alias as reusable") + +console.log("Playground SQLite alias smoke passed")