Skip to content

Commit 2b11f8c

Browse files
committed
Settle the API shape
1 parent 0a57903 commit 2b11f8c

File tree

16 files changed

+156
-158
lines changed

16 files changed

+156
-158
lines changed

.eslintrc.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111
{
1212
"enforceBuildableLibDependency": true,
1313
"allow": [],
14-
"depConstraints": []
14+
"depConstraints": [
15+
{
16+
"sourceTag": "*",
17+
"notDependOnLibsWithTags": ["scope:web-client"]
18+
}
19+
]
1520
}
1621
],
1722
"no-inner-declarations": 0,

packages/php-wasm/cli/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"options": {
3535
"scriptPath": "dist/packages/php-wasm/cli/main.js"
3636
},
37-
"dependsOn": ["build", "^build-for-cli-run"]
37+
"dependsOn": ["build"]
3838
},
3939
"publish": {
4040
"executor": "nx:run-commands",

packages/php-wasm/node/.eslintrc.json

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,7 @@
44
"overrides": [
55
{
66
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7-
"rules": {
8-
"@nrwl/nx/enforce-module-boundaries": [
9-
"error",
10-
{
11-
"enforceBuildableLibDependency": true,
12-
"allow": ["@php-wasm/universal"]
13-
}
14-
]
15-
}
7+
"rules": {}
168
},
179
{
1810
"files": ["*.ts", "*.tsx"],

packages/php-wasm/progress/src/lib/progress-tracker.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,10 @@ export class ProgressTracker extends EventTarget {
153153
* subTracker1.set(100);
154154
* ```
155155
*/
156-
stage(weight: number, caption = ''): ProgressTracker {
156+
stage(weight?: number, caption = ''): ProgressTracker {
157+
if (!weight) {
158+
weight = this._selfWeight;
159+
}
157160
if (this._selfWeight - weight < -Number.EPSILON) {
158161
throw new Error(
159162
`Cannot add a stage with weight ${weight} as the total weight of registered stages would exceed 1.`

packages/php-wasm/universal/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"sourceRoot": "packages/php-wasm/universal/src",
55
"projectType": "library",
66
"targets": {
7-
"build-for-cli-run": {
7+
"build": {
88
"executor": "@nrwl/vite:build",
99
"outputs": ["{options.outputPath}"],
1010
"options": {

packages/php-wasm/web/.eslintrc.json

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,7 @@
44
"overrides": [
55
{
66
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7-
"rules": {
8-
"@nrwl/nx/enforce-module-boundaries": [
9-
"error",
10-
{
11-
"allow": ["php-wasm-universal"]
12-
}
13-
]
14-
}
7+
"rules": {}
158
},
169
{
1710
"files": ["*.ts", "*.tsx"],

packages/playground/blueprints/src/lib/steps/apply-wordpress-patches/index.ts

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ export interface PatchOptions {
99
patchSiteUrl?: boolean;
1010
disableSiteHealth?: boolean;
1111
disableWpNewBlogNotification?: boolean;
12-
replaceRequestsTransports?: boolean;
13-
allowWpOrgHosts?: boolean;
1412
}
1513

1614
export async function applyWordPressPatches(
@@ -38,9 +36,6 @@ export async function applyWordPressPatches(
3836
if (options.disableWpNewBlogNotification !== false) {
3937
await patch.disableWpNewBlogNotification();
4038
}
41-
if (options.allowWpOrgHosts !== false) {
42-
await patch.allowWpOrgHosts();
43-
}
4439
}
4540

4641
class WordPressPatcher {
@@ -78,6 +73,7 @@ class WordPressPatcher {
7873
'<?php phpinfo(); '
7974
);
8075
}
76+
8177
async patchSiteUrl() {
8278
await patchFile(
8379
this.php,
@@ -91,6 +87,7 @@ class WordPressPatcher {
9187
?>${contents}`
9288
);
9389
}
90+
9491
async disableSiteHealth() {
9592
await patchFile(
9693
this.php,
@@ -102,30 +99,14 @@ class WordPressPatcher {
10299
)
103100
);
104101
}
102+
105103
async disableWpNewBlogNotification() {
106104
await patchFile(
107105
this.php,
108106
`${this.wordpressPath}/wp-config.php`,
109-
// The original version of this function crashes WASM WordPress, let's define an empty one instead.
107+
// The original version of this function crashes WASM PHP, let's define an empty one instead.
110108
(contents) =>
111109
`${contents} function wp_new_blog_notification(...$args){} `
112110
);
113111
}
114-
115-
async allowWpOrgHosts() {
116-
await this.php.mkdirTree(`${this.wordpressPath}/wp-content/mu-plugins`);
117-
await this.php.writeFile(
118-
`${this.wordpressPath}/wp-content/mu-plugins/0-allow-wp-org.php`,
119-
`<?php
120-
// Needed because gethostbyname( 'wordpress.org' ) returns
121-
// a private network IP address for some reason.
122-
add_filter( 'allowed_redirect_hosts', function( $deprecated = '' ) {
123-
return array(
124-
'wordpress.org',
125-
'api.wordpress.org',
126-
'downloads.wordpress.org',
127-
);
128-
} );`
129-
);
130-
}
131112
}

packages/playground/client/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,5 +121,5 @@
121121
}
122122
}
123123
},
124-
"tags": []
124+
"tags": ["scope:web-client"]
125125
}

packages/playground/client/src/index.ts

Lines changed: 72 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -25,69 +25,79 @@ export interface StartPlaygroundOptions {
2525
blueprint?: Blueprint;
2626
}
2727

28-
const officialRemoteOrigin = 'https://playground.wordpress.net';
29-
3028
/**
3129
* Loads playground in iframe and returns a PlaygroundClient instance.
32-
* Optionally
3330
*
3431
* @param iframe Any iframe with Playground's remote.html loaded.
3532
* @param options Options for loading the playground.
3633
* @returns A PlaygroundClient instance.
3734
*/
38-
export async function startPlayground(
39-
options: StartPlaygroundOptions
40-
): Promise<PlaygroundClient> {
41-
const blueprint: Blueprint = {
42-
...(options.blueprint || {}),
43-
preferredVersions: {
44-
php: '8.0',
45-
wp: 'latest',
46-
...(options.blueprint?.preferredVersions || {}),
47-
},
48-
};
49-
const tracker = options.progressTracker || new ProgressTracker();
50-
tracker.setCaption('Preparing WordPress');
35+
export async function startPlaygroundWeb({
36+
iframe,
37+
blueprint,
38+
remoteUrl,
39+
progressTracker = new ProgressTracker(),
40+
disableProgressBar,
41+
}: StartPlaygroundOptions): Promise<PlaygroundClient> {
42+
assertValidRemote(remoteUrl);
43+
remoteUrl = setQueryParams(remoteUrl, {
44+
progressbar: !disableProgressBar,
45+
});
46+
progressTracker.setCaption('Preparing WordPress');
47+
if (!blueprint) {
48+
return doStartPlaygroundWeb(iframe, remoteUrl, progressTracker);
49+
}
5150

5251
const compiled = compileBlueprint(blueprint, {
53-
progress: tracker.stage(0.5),
52+
progress: progressTracker.stage(0.5),
5453
});
54+
const playground = await doStartPlaygroundWeb(
55+
iframe,
56+
setQueryParams(remoteUrl, {
57+
php: compiled.versions.php,
58+
wp: compiled.versions.wp,
59+
}),
60+
progressTracker
61+
);
62+
await runBlueprintSteps(compiled, playground);
63+
await playground.goTo(compiled.landingPage);
64+
return playground;
65+
}
5566

56-
// Load playground in an iframe
67+
/**
68+
* Internal function to connect an iframe to the playground remote.
69+
*
70+
* @param iframe
71+
* @param remoteUrl
72+
* @param progressTracker
73+
* @returns
74+
*/
75+
async function doStartPlaygroundWeb(
76+
iframe: HTMLIFrameElement,
77+
remoteUrl: string,
78+
progressTracker: ProgressTracker
79+
) {
5780
await new Promise((resolve) => {
58-
options.iframe.src = remoteURL(
59-
options.remoteUrl,
60-
compiled?.versions.php,
61-
compiled?.versions.wp,
62-
options.disableProgressBar
63-
);
64-
options.iframe.addEventListener('load', resolve, false);
81+
iframe.src = remoteUrl;
82+
iframe.addEventListener('load', resolve, false);
6583
});
6684

67-
// Connect the Comlink client
68-
const playground = createClient(options.iframe);
85+
// Connect the Comlink client and wait until the
86+
// playground is ready.
87+
const playground = consumeAPI<PlaygroundClient>(
88+
iframe.contentWindow!
89+
) as PlaygroundClient;
6990
await playground.connected;
70-
71-
// Wait for playground to be ready and display the progress
72-
tracker.pipe(playground);
73-
const downloadTracker = compiled.steps.length
74-
? tracker.stage(0.5)
75-
: tracker;
76-
await playground.onDownloadProgress(downloadTracker.loadingListener);
91+
progressTracker.pipe(playground);
92+
await playground.onDownloadProgress(
93+
progressTracker.stage().loadingListener
94+
);
7795
await playground.isReady();
78-
79-
await runBlueprintSteps(compiled, playground);
80-
await playground.goTo(compiled.landingPage);
81-
8296
return playground;
8397
}
8498

85-
function remoteURL(
86-
remoteHtmlUrl: string,
87-
php: string,
88-
wp: string,
89-
disableProgressBar = false
90-
) {
99+
const officialRemoteOrigin = 'https://playground.wordpress.net';
100+
function assertValidRemote(remoteHtmlUrl: string) {
91101
const url = new URL(remoteHtmlUrl);
92102
if (
93103
(url.origin === officialRemoteOrigin || url.hostname === 'localhost') &&
@@ -98,20 +108,22 @@ function remoteURL(
98108
`Expected origin to be ${officialRemoteOrigin}/remote.html.`
99109
);
100110
}
111+
}
101112

102-
const qs = new URLSearchParams({
103-
php,
104-
wp,
105-
});
106-
if (!disableProgressBar) {
107-
qs.set('progressbar', '1');
113+
function setQueryParams(url: string, params: Record<string, unknown>) {
114+
const urlObject = new URL(url);
115+
const qs = new URLSearchParams(urlObject.search);
116+
for (const [key, value] of Object.entries(params)) {
117+
if (value !== undefined && value !== null && value !== false) {
118+
qs.set(key, value.toString());
119+
}
108120
}
109-
url.search = qs.toString();
110-
return url.toString();
121+
urlObject.search = qs.toString();
122+
return urlObject.toString();
111123
}
112124

113125
/**
114-
* @deprecated Use `loadPlayground` instead.
126+
* @deprecated Use `startPlayground` instead.
115127
*
116128
* @param iframe Any iframe with Playground's remote.html loaded.
117129
* @param options Optional. If `loadRemote` is set, the iframe's `src` will be set to that URL.
@@ -122,24 +134,18 @@ export async function connectPlayground(
122134
iframe: HTMLIFrameElement,
123135
options?: { loadRemote?: string }
124136
): Promise<PlaygroundClient> {
137+
console.warn(
138+
'`connectPlayground` is deprecated and will be removed. Use `startPlayground` instead.'
139+
);
125140
if (options?.loadRemote) {
126-
return startPlayground({
141+
return startPlaygroundWeb({
127142
iframe,
128143
remoteUrl: options.loadRemote,
129144
});
130145
}
131-
const client = createClient(iframe);
146+
const client = consumeAPI<PlaygroundClient>(
147+
iframe.contentWindow!
148+
) as PlaygroundClient;
132149
await client.connected;
133150
return client;
134151
}
135-
136-
export function createClient(iframe: HTMLIFrameElement): PlaygroundClient {
137-
const client = consumeAPI<PlaygroundClient>(iframe.contentWindow!);
138-
139-
/*
140-
* consumeAPI returns Remote<PlaygroundClient>. However,
141-
* PlaygroundClient is has a better DX while still being
142-
* compatible with Remote<PlaygroundClient>. Let's typecast:
143-
*/
144-
return client as PlaygroundClient;
145-
}

packages/playground/node/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"name": "@wp-playground/node",
3-
"version": "0.0.1"
3+
"version": "0.0.1",
4+
"private": true
45
}

0 commit comments

Comments
 (0)