Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/playground/cli/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"sourceRoot": "packages/playground/cli/src",
"projectType": "library",
"tags": ["scope:php-wasm-public", "scope:cli"],
"implicitDependencies": ["playground-mariadb"],
"targets": {
"build": {
"executor": "nx:noop",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,20 @@ export class BlueprintsV1Handler {
this.getEffectiveBlueprint()
);

// When using MariaDB WASM, define the MySQL credentials
// as PHP constants so WordPress connects to the protocol
// server instead of trying to use SQLite.
let constants = mergeDefinedConstants(this.args);
if (this.args.database === 'mariadb' && this.args.mariadbPort) {
constants = {
...constants,
DB_HOST: `127.0.0.1:${this.args.mariadbPort}`,
DB_USER: 'root',
DB_PASSWORD: '',
DB_NAME: 'wordpress',
};
}

// TODO: Fix this type issue that requires the cast to unknown
await (
playground as unknown as PlaygroundCliBlueprintV1Worker
Expand All @@ -138,7 +152,7 @@ export class BlueprintsV1Handler {
wordPressZip && (await wordPressZip!.arrayBuffer()),
sqliteIntegrationPluginZip:
await sqliteIntegrationPluginZip?.arrayBuffer(),
constants: mergeDefinedConstants(this.args),
constants,
},
workerPostInstallMountsPort
);
Expand Down
8 changes: 8 additions & 0 deletions packages/playground/cli/src/cli-output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface ConfigSummary {
/** All mounts (both manual and auto-detected). Auto-mounts have autoMounted: true */
mounts: Mount[];
blueprint?: string;
database?: string;
}

export class CLIOutput {
Expand Down Expand Up @@ -120,6 +121,13 @@ export class CLIOutput {
`${this.dim('PHP')} ${this.cyan(config.phpVersion)} ${this.dim('WordPress')} ${this.cyan(config.wpVersion)}`
);

// Database engine
if (config.database === 'mariadb') {
lines.push(
`${this.dim('Database')} ${this.cyan('MariaDB WASM')}`
);
}

// Extensions
const extensions: string[] = [];
if (config.intl) extensions.push('intl');
Expand Down
65 changes: 65 additions & 0 deletions packages/playground/cli/src/run-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import {
PHPMYADMIN_INSTALL_PATH,
} from '@wp-playground/tools';
import { jspi } from 'wasm-feature-detect';
import type { MariaDBServer } from '@wp-playground/mariadb';

// Inlined worker URLs for static analysis by downstream bundlers
// These are replaced at build time by the Vite plugin in vite.config.ts
Expand Down Expand Up @@ -227,6 +228,20 @@ export async function parseOptionsAndRunCLI(argsToParse: string[]) {
type: 'boolean',
default: false,
},
database: {
describe:
'Database engine to use. "sqlite" uses the bundled SQLite integration plugin. ' +
'"mariadb" starts a MariaDB WASM server in-process and connects WordPress via MySQL protocol.',
type: 'string',
choices: ['sqlite', 'mariadb'] as const,
default: 'sqlite',
},
'mariadb-wasm-module': {
describe:
'Path to the mariadb.js Emscripten module produced by the mariadb-wasm build. ' +
'Required when --database=mariadb. The mariadb.wasm file must be in the same directory.',
type: 'string',
},
// Hidden - Deprecated in favor of verbosity
quiet: {
describe: 'Do not output logs and progress messages.',
Expand Down Expand Up @@ -442,6 +457,9 @@ export async function parseOptionsAndRunCLI(argsToParse: string[]) {
'define-number': sharedOptions['define-number'],
// Tools
phpmyadmin: sharedOptions['phpmyadmin'],
// Database
database: sharedOptions['database'],
'mariadb-wasm-module': sharedOptions['mariadb-wasm-module'],
};

const buildSnapshotOnlyOptions: Record<string, YargsOptions> = {
Expand Down Expand Up @@ -846,6 +864,15 @@ export interface RunCLIArgs {
*/
'define-number'?: Record<string, number>;

// --------- Database args -----------
database?: 'sqlite' | 'mariadb';
'mariadb-wasm-module'?: string;
/**
* When --database=mariadb, the main thread starts a MySQL protocol
* server and stores its port here so workers can connect.
*/
mariadbPort?: number;

// --------- Blueprint V1 args -----------
skipSqliteSetup?: boolean;
followSymlinks?: boolean;
Expand Down Expand Up @@ -989,6 +1016,18 @@ export async function runCLI(args: RunCLIArgs): Promise<RunCLIServer | void> {
args.memcached = await jspi();
}

// When --database=mariadb is selected, skip SQLite setup and validate
// that the WASM module path is provided.
if (args.database === 'mariadb') {
args.skipSqliteSetup = true;
if (!args['mariadb-wasm-module']) {
throw new Error(
'--mariadb-wasm-module is required when --database=mariadb. ' +
'Provide the path to the mariadb.js file produced by the mariadb-wasm build.'
);
}
}

// Setup phpMyAdmin if enabled.
if (args.phpmyadmin) {
if (true === args.phpmyadmin) {
Expand Down Expand Up @@ -1026,6 +1065,7 @@ export async function runCLI(args: RunCLIArgs): Promise<RunCLIServer | void> {
],
blueprint:
typeof args.blueprint === 'string' ? args.blueprint : undefined,
database: args.database,
});
}

Expand All @@ -1037,6 +1077,7 @@ export async function runCLI(args: RunCLIArgs): Promise<RunCLIServer | void> {

let wordPressReady = false;
let isFirstRequest = true;
let mariadbServer: MariaDBServer | undefined;

const server = await startServer({
port: args.port
Expand All @@ -1049,6 +1090,27 @@ export async function runCLI(args: RunCLIArgs): Promise<RunCLIServer | void> {
const serverUrl = `http://${host}:${port}`;
const siteUrl = args['site-url'] || serverUrl;

// Start MariaDB WASM server if --database=mariadb.
// This must happen before worker threads are spawned so
// the MySQL port is available when PHP boots.
if (args.database === 'mariadb') {
const { loadMariaDBModule, startMySQLProtocolServer } =
await import('@wp-playground/mariadb');

cliOutput.updateProgress('Starting MariaDB WASM');
const bridge = await loadMariaDBModule(
args['mariadb-wasm-module']!
);
mariadbServer = await startMySQLProtocolServer({
bridge,
defaultDatabase: 'wordpress',
});
args.mariadbPort = mariadbServer.port;
logger.debug(
`MariaDB WASM server listening on port ${mariadbServer.port}`
);
}
Comment thread
adamziel marked this conversation as resolved.
Outdated

/**
* With HTTP 1.1, browsers typically support 6 parallel connections per domain.
* > browsers open several connections to each domain,
Expand Down Expand Up @@ -1388,6 +1450,9 @@ export async function runCLI(args: RunCLIArgs): Promise<RunCLIServer | void> {
server.closeAllConnections();
});
}
if (mariadbServer) {
await mariadbServer.close();
}
await nativeDir.cleanup();
};

Expand Down
32 changes: 32 additions & 0 deletions packages/playground/mariadb/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"extends": ["../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": [
"error",
{
"ignoredFiles": [
"{projectRoot}/vite.config.{js,ts,mjs,mts}"
]
}
]
}
}
]
}
31 changes: 31 additions & 0 deletions packages/playground/mariadb/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@wp-playground/mariadb",
"version": "3.1.18",
"description": "MariaDB WASM integration for WordPress Playground",
"repository": {
"type": "git",
"url": "https://github.com/WordPress/wordpress-playground"
},
"homepage": "https://developer.wordpress.org/playground",
"author": "The WordPress contributors",
"license": "GPL-2.0-or-later",
"type": "module",
"main": "./index.cjs",
"module": "./index.js",
"types": "index.d.ts",
"engines": {
"node": ">=20.10.0",
"npm": ">=10.2.3"
},
"exports": {
".": {
"import": "./index.js",
"require": "./index.cjs"
},
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public",
"directory": "../../../dist/packages/playground/mariadb"
}
}
59 changes: 59 additions & 0 deletions packages/playground/mariadb/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"name": "playground-mariadb",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/playground/mariadb/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "nx:noop",
"dependsOn": ["build:package-json"]
},
"build:package-json": {
"executor": "@wp-playground/nx-extensions:package-json",
"options": {
"tsConfig": "packages/playground/mariadb/tsconfig.lib.json",
"outputPath": "dist/packages/playground/mariadb",
"buildTarget": "playground-mariadb:build:bundle:production"
}
},
"build:bundle": {
"executor": "@nx/vite:build",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"outputPath": "dist/packages/playground/mariadb"
},
"configurations": {
"development": {
"mode": "development"
},
"production": {
"mode": "production"
}
},
"dependsOn": ["^build"]
},
"test": {
"executor": "nx:noop",
"dependsOn": ["test:vite"]
},
"test:vite": {
"executor": "@nx/vitest:test",
"outputs": ["{workspaceRoot}/coverage/packages/playground/mariadb"],
"options": {
"passWithNoTests": true,
"reportsDirectory": "../../../coverage/packages/playground/mariadb"
}
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"],
"options": {
"useFlatConfig": false,
"lintFilePatterns": ["packages/playground/mariadb/**/*.ts"],
"maxWarnings": 0
}
}
}
}
17 changes: 17 additions & 0 deletions packages/playground/mariadb/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export {
MariaDBBridge,
MariaDBQueryError,
loadMariaDBModule,
} from './lib/mariadb-wasm-bridge';
export type {
MariaDBEmscriptenModule,
ColumnInfo,
QueryResult,
} from './lib/mariadb-wasm-bridge';
export {
startMySQLProtocolServer,
} from './lib/mysql-protocol-server';
export type {
MariaDBServer,
MariaDBServerOptions,
} from './lib/mysql-protocol-server';
Loading
Loading