@wp-playground/blueprints 0.1.40 → 0.1.42
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/index.cjs +133 -0
- package/index.d.ts +7 -0
- package/index.js +2081 -0
- package/lib/blueprint.d.ts +27 -0
- package/lib/compile.d.ts +37 -0
- package/lib/resources.d.ts +211 -0
- package/lib/steps/activate-plugin.d.ts +12 -0
- package/lib/steps/apply-wordpress-patches/index.d.ts +12 -0
- package/lib/steps/client-methods.d.ts +56 -0
- package/lib/steps/common.d.ts +7 -0
- package/lib/steps/define-site-url.d.ts +12 -0
- package/lib/steps/define-wp-config-consts.d.ts +12 -0
- package/{src/lib/steps/handlers.ts → lib/steps/handlers.d.ts} +1 -12
- package/lib/steps/import-export.d.ts +67 -0
- package/lib/steps/index.d.ts +26 -0
- package/lib/steps/install-plugin.d.ts +22 -0
- package/lib/steps/install-theme.d.ts +22 -0
- package/lib/steps/login.d.ts +16 -0
- package/lib/steps/migration.d.ts +2 -0
- package/lib/steps/run-wp-installation-wizard.d.ts +16 -0
- package/lib/steps/site-data.d.ts +12 -0
- package/package.json +4 -3
- package/.eslintrc.json +0 -18
- package/LICENSE +0 -339
- package/README.md +0 -11
- package/project.json +0 -58
- package/src/index.ts +0 -31
- package/src/lib/blueprint.ts +0 -28
- package/src/lib/compile.spec.ts +0 -34
- package/src/lib/compile.ts +0 -262
- package/src/lib/resources.ts +0 -417
- package/src/lib/steps/activate-plugin.ts +0 -35
- package/src/lib/steps/apply-wordpress-patches/index.ts +0 -113
- package/src/lib/steps/apply-wordpress-patches/wp-content/mu-plugins/1-show-admin-credentials-on-wp-login.php +0 -15
- package/src/lib/steps/client-methods.ts +0 -121
- package/src/lib/steps/common.ts +0 -30
- package/src/lib/steps/define-site-url.ts +0 -25
- package/src/lib/steps/define-wp-config-consts.ts +0 -45
- package/src/lib/steps/import-export.ts +0 -225
- package/src/lib/steps/index.ts +0 -67
- package/src/lib/steps/install-plugin.ts +0 -145
- package/src/lib/steps/install-theme.ts +0 -99
- package/src/lib/steps/login.ts +0 -37
- package/src/lib/steps/migration.ts +0 -63
- package/src/lib/steps/run-wp-installation-wizard.ts +0 -38
- package/src/lib/steps/site-data.ts +0 -58
- package/tsconfig.json +0 -23
- package/tsconfig.lib.json +0 -10
- package/tsconfig.spec.json +0 -19
- package/vite.config.ts +0 -58
package/src/lib/compile.ts
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
import { ProgressTracker } from '@php-wasm/progress';
|
|
2
|
-
import { Semaphore } from '@php-wasm/util';
|
|
3
|
-
import {
|
|
4
|
-
LatestSupportedPHPVersion,
|
|
5
|
-
SupportedPHPVersion,
|
|
6
|
-
SupportedPHPVersions,
|
|
7
|
-
UniversalPHP,
|
|
8
|
-
} from '@php-wasm/universal';
|
|
9
|
-
import { isFileReference, Resource } from './resources';
|
|
10
|
-
import { Step, StepDefinition } from './steps';
|
|
11
|
-
import * as stepHandlers from './steps/handlers';
|
|
12
|
-
import { Blueprint } from './blueprint';
|
|
13
|
-
|
|
14
|
-
export type CompiledStep = (php: UniversalPHP) => Promise<void> | void;
|
|
15
|
-
|
|
16
|
-
const supportedWordPressVersions = ['6.2', '6.1', '6.0', '5.9'] as const;
|
|
17
|
-
type supportedWordPressVersion = (typeof supportedWordPressVersions)[number];
|
|
18
|
-
export interface CompiledBlueprint {
|
|
19
|
-
/** The requested versions of PHP and WordPress for the blueprint */
|
|
20
|
-
versions: {
|
|
21
|
-
php: SupportedPHPVersion;
|
|
22
|
-
wp: supportedWordPressVersion;
|
|
23
|
-
};
|
|
24
|
-
/** The compiled steps for the blueprint */
|
|
25
|
-
run: (playground: UniversalPHP) => Promise<void>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export type OnStepCompleted = (output: any, step: StepDefinition) => any;
|
|
29
|
-
|
|
30
|
-
export interface CompileBlueprintOptions {
|
|
31
|
-
/** Optional progress tracker to monitor progress */
|
|
32
|
-
progress?: ProgressTracker;
|
|
33
|
-
/** Optional semaphore to control access to a shared resource */
|
|
34
|
-
semaphore?: Semaphore;
|
|
35
|
-
/** Optional callback with step output */
|
|
36
|
-
onStepCompleted?: OnStepCompleted;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Compiles Blueprint into a form that can be executed.
|
|
41
|
-
*
|
|
42
|
-
* @param playground The PlaygroundClient to use for the compilation
|
|
43
|
-
* @param blueprint The bBueprint to compile
|
|
44
|
-
* @param options Additional options for the compilation
|
|
45
|
-
* @returns The compiled blueprint
|
|
46
|
-
*/
|
|
47
|
-
export function compileBlueprint(
|
|
48
|
-
blueprint: Blueprint,
|
|
49
|
-
{
|
|
50
|
-
progress = new ProgressTracker(),
|
|
51
|
-
semaphore = new Semaphore({ concurrency: 3 }),
|
|
52
|
-
onStepCompleted = () => {},
|
|
53
|
-
}: CompileBlueprintOptions = {}
|
|
54
|
-
): CompiledBlueprint {
|
|
55
|
-
const steps = (blueprint.steps || []).filter(isStepDefinition);
|
|
56
|
-
|
|
57
|
-
const totalProgressWeight = steps.reduce(
|
|
58
|
-
(total, step) => total + (step.progress?.weight || 1),
|
|
59
|
-
0
|
|
60
|
-
);
|
|
61
|
-
const compiled = steps.map((step) =>
|
|
62
|
-
compileStep(step, {
|
|
63
|
-
semaphore,
|
|
64
|
-
rootProgressTracker: progress,
|
|
65
|
-
totalProgressWeight,
|
|
66
|
-
})
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
versions: {
|
|
71
|
-
php: compileVersion(
|
|
72
|
-
blueprint.preferredVersions?.php,
|
|
73
|
-
SupportedPHPVersions,
|
|
74
|
-
LatestSupportedPHPVersion
|
|
75
|
-
),
|
|
76
|
-
wp: compileVersion(
|
|
77
|
-
blueprint.preferredVersions?.wp,
|
|
78
|
-
supportedWordPressVersions,
|
|
79
|
-
'6.2'
|
|
80
|
-
),
|
|
81
|
-
},
|
|
82
|
-
run: async (playground: UniversalPHP) => {
|
|
83
|
-
try {
|
|
84
|
-
// Start resolving resources early
|
|
85
|
-
for (const { resources } of compiled) {
|
|
86
|
-
for (const resource of resources) {
|
|
87
|
-
resource.setPlayground(playground);
|
|
88
|
-
if (resource.isAsync) {
|
|
89
|
-
resource.resolve();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
for (const { run, step } of compiled) {
|
|
95
|
-
const result = await run(playground);
|
|
96
|
-
onStepCompleted(result, step);
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
await (playground as any).goTo(
|
|
100
|
-
blueprint.landingPage || '/'
|
|
101
|
-
);
|
|
102
|
-
} catch (e) {
|
|
103
|
-
/*
|
|
104
|
-
* NodePHP exposes no goTo method.
|
|
105
|
-
* We can't use `goto` in playground here,
|
|
106
|
-
* because it may be a Comlink proxy object
|
|
107
|
-
* with no such method.
|
|
108
|
-
*/
|
|
109
|
-
}
|
|
110
|
-
} finally {
|
|
111
|
-
progress.finish();
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Compiles a preferred version string into a supported version
|
|
119
|
-
*
|
|
120
|
-
* @param value The value to compile
|
|
121
|
-
* @param supported The list of supported versions
|
|
122
|
-
* @param latest The latest supported version
|
|
123
|
-
* @returns The compiled version
|
|
124
|
-
*/
|
|
125
|
-
function compileVersion<T>(
|
|
126
|
-
value: string | undefined | null,
|
|
127
|
-
supported: readonly T[],
|
|
128
|
-
latest: string
|
|
129
|
-
): T {
|
|
130
|
-
if (value && supported.includes(value as any)) {
|
|
131
|
-
return value as T;
|
|
132
|
-
}
|
|
133
|
-
return latest as T;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Determines if a step is a StepDefinition object
|
|
138
|
-
*
|
|
139
|
-
* @param step The object to test
|
|
140
|
-
* @returns Whether the object is a StepDefinition
|
|
141
|
-
*/
|
|
142
|
-
function isStepDefinition(
|
|
143
|
-
step: Step | string | undefined | false | null
|
|
144
|
-
): step is StepDefinition {
|
|
145
|
-
return !!(typeof step === 'object' && step);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
interface CompileStepArgsOptions {
|
|
149
|
-
/** Optional semaphore to control access to a shared resource */
|
|
150
|
-
semaphore?: Semaphore;
|
|
151
|
-
/** The root progress tracker for the compilation */
|
|
152
|
-
rootProgressTracker: ProgressTracker;
|
|
153
|
-
/** The total progress weight of all the steps in the blueprint */
|
|
154
|
-
totalProgressWeight: number;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Compiles a single Blueprint step into a form that can be executed
|
|
159
|
-
*
|
|
160
|
-
* @param playground The PlaygroundClient to use for the compilation
|
|
161
|
-
* @param step The step to compile
|
|
162
|
-
* @param options Additional options for the compilation
|
|
163
|
-
* @returns The compiled step
|
|
164
|
-
*/
|
|
165
|
-
function compileStep<S extends StepDefinition>(
|
|
166
|
-
step: S,
|
|
167
|
-
{
|
|
168
|
-
semaphore,
|
|
169
|
-
rootProgressTracker,
|
|
170
|
-
totalProgressWeight,
|
|
171
|
-
}: CompileStepArgsOptions
|
|
172
|
-
): { run: CompiledStep; step: S; resources: Array<Resource> } {
|
|
173
|
-
const stepProgress = rootProgressTracker.stage(
|
|
174
|
-
(step.progress?.weight || 1) / totalProgressWeight
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
const args: any = {};
|
|
178
|
-
for (const key of Object.keys(step)) {
|
|
179
|
-
let value = (step as any)[key];
|
|
180
|
-
if (isFileReference(value)) {
|
|
181
|
-
value = Resource.create(value, {
|
|
182
|
-
semaphore,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
args[key] = value;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const run = async (playground: UniversalPHP) => {
|
|
189
|
-
try {
|
|
190
|
-
stepProgress.fillSlowly();
|
|
191
|
-
return await stepHandlers[step.step](
|
|
192
|
-
playground,
|
|
193
|
-
await resolveArguments(args),
|
|
194
|
-
{
|
|
195
|
-
tracker: stepProgress,
|
|
196
|
-
initialCaption: step.progress?.caption,
|
|
197
|
-
}
|
|
198
|
-
);
|
|
199
|
-
} finally {
|
|
200
|
-
stepProgress.finish();
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* The weight of each async resource is the same, and is the same as the
|
|
206
|
-
* weight of the step itself.
|
|
207
|
-
*/
|
|
208
|
-
const resources = getResources(args);
|
|
209
|
-
const asyncResources = getResources(args).filter(
|
|
210
|
-
(resource) => resource.isAsync
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
const evenWeight = 1 / (asyncResources.length + 1);
|
|
214
|
-
for (const resource of asyncResources) {
|
|
215
|
-
resource.progress = stepProgress.stage(evenWeight);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return { run, step, resources };
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Gets the resources used by a specific compiled step
|
|
223
|
-
*
|
|
224
|
-
* @param step The compiled step
|
|
225
|
-
* @returns The resources used by the compiled step
|
|
226
|
-
*/
|
|
227
|
-
function getResources<S extends StepDefinition>(args: S) {
|
|
228
|
-
const result: Resource[] = [];
|
|
229
|
-
for (const argName in args) {
|
|
230
|
-
const resourceMaybe = (args as any)[argName];
|
|
231
|
-
if (resourceMaybe instanceof Resource) {
|
|
232
|
-
result.push(resourceMaybe);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return result;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Replaces Resource objects with their resolved values
|
|
240
|
-
*
|
|
241
|
-
* @param step The compiled step
|
|
242
|
-
* @returns The resources used by the compiled step
|
|
243
|
-
*/
|
|
244
|
-
async function resolveArguments<T extends Record<string, unknown>>(args: T) {
|
|
245
|
-
const resolved: any = {};
|
|
246
|
-
for (const argName in args) {
|
|
247
|
-
const resourceMaybe = (args as any)[argName];
|
|
248
|
-
if (resourceMaybe instanceof Resource) {
|
|
249
|
-
resolved[argName] = await resourceMaybe.resolve();
|
|
250
|
-
} else {
|
|
251
|
-
resolved[argName] = resourceMaybe;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
return resolved;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export async function runBlueprintSteps(
|
|
258
|
-
compiledBlueprint: CompiledBlueprint,
|
|
259
|
-
playground: UniversalPHP
|
|
260
|
-
) {
|
|
261
|
-
await compiledBlueprint.run(playground);
|
|
262
|
-
}
|
package/src/lib/resources.ts
DELETED
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
cloneResponseMonitorProgress,
|
|
3
|
-
ProgressTracker,
|
|
4
|
-
} from '@php-wasm/progress';
|
|
5
|
-
import { UniversalPHP } from '@php-wasm/universal';
|
|
6
|
-
import { Semaphore } from '@php-wasm/util';
|
|
7
|
-
import { zipNameToHumanName } from './steps/common';
|
|
8
|
-
|
|
9
|
-
export const ResourceTypes = [
|
|
10
|
-
'vfs',
|
|
11
|
-
'literal',
|
|
12
|
-
'wordpress.org/themes',
|
|
13
|
-
'wordpress.org/plugins',
|
|
14
|
-
'url',
|
|
15
|
-
] as const;
|
|
16
|
-
|
|
17
|
-
export type VFSReference = {
|
|
18
|
-
/** Identifies the file resource as Virtual File System (VFS) */
|
|
19
|
-
resource: 'vfs';
|
|
20
|
-
/** The path to the file in the VFS */
|
|
21
|
-
path: string;
|
|
22
|
-
};
|
|
23
|
-
export type LiteralReference = {
|
|
24
|
-
/** Identifies the file resource as a literal file */
|
|
25
|
-
resource: 'literal';
|
|
26
|
-
/** The name of the file */
|
|
27
|
-
name: string;
|
|
28
|
-
/** The contents of the file */
|
|
29
|
-
contents: string | Uint8Array;
|
|
30
|
-
};
|
|
31
|
-
export type CoreThemeReference = {
|
|
32
|
-
/** Identifies the file resource as a WordPress Core theme */
|
|
33
|
-
resource: 'wordpress.org/themes';
|
|
34
|
-
/** The slug of the WordPress Core theme */
|
|
35
|
-
slug: string;
|
|
36
|
-
};
|
|
37
|
-
export type CorePluginReference = {
|
|
38
|
-
/** Identifies the file resource as a WordPress Core plugin */
|
|
39
|
-
resource: 'wordpress.org/plugins';
|
|
40
|
-
/** The slug of the WordPress Core plugin */
|
|
41
|
-
slug: string;
|
|
42
|
-
};
|
|
43
|
-
export type UrlReference = {
|
|
44
|
-
/** Identifies the file resource as a URL */
|
|
45
|
-
resource: 'url';
|
|
46
|
-
/** The URL of the file */
|
|
47
|
-
url: string;
|
|
48
|
-
/** Optional caption for displaying a progress message */
|
|
49
|
-
caption?: string;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export type FileReference =
|
|
53
|
-
| VFSReference
|
|
54
|
-
| LiteralReference
|
|
55
|
-
| CoreThemeReference
|
|
56
|
-
| CorePluginReference
|
|
57
|
-
| UrlReference;
|
|
58
|
-
|
|
59
|
-
export function isFileReference(ref: any): ref is FileReference {
|
|
60
|
-
return (
|
|
61
|
-
ref &&
|
|
62
|
-
typeof ref === 'object' &&
|
|
63
|
-
typeof ref.resource === 'string' &&
|
|
64
|
-
ResourceTypes.includes(ref.resource)
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface ResourceOptions {
|
|
69
|
-
/** Optional semaphore to limit concurrent downloads */
|
|
70
|
-
semaphore?: Semaphore;
|
|
71
|
-
progress?: ProgressTracker;
|
|
72
|
-
}
|
|
73
|
-
export abstract class Resource {
|
|
74
|
-
/** Optional progress tracker to monitor progress */
|
|
75
|
-
public abstract progress?: ProgressTracker;
|
|
76
|
-
/** A Promise that resolves to the file contents */
|
|
77
|
-
protected promise?: Promise<File>;
|
|
78
|
-
|
|
79
|
-
protected playground?: UniversalPHP;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Creates a new Resource based on the given file reference
|
|
83
|
-
*
|
|
84
|
-
* @param ref The file reference to create the Resource for
|
|
85
|
-
* @param options Additional options for the Resource
|
|
86
|
-
* @returns A new Resource instance
|
|
87
|
-
*/
|
|
88
|
-
static create(
|
|
89
|
-
ref: FileReference,
|
|
90
|
-
{ semaphore, progress }: ResourceOptions
|
|
91
|
-
): Resource {
|
|
92
|
-
let resource: Resource;
|
|
93
|
-
switch (ref.resource) {
|
|
94
|
-
case 'vfs':
|
|
95
|
-
resource = new VFSResource(ref, progress);
|
|
96
|
-
break;
|
|
97
|
-
case 'literal':
|
|
98
|
-
resource = new LiteralResource(ref, progress);
|
|
99
|
-
break;
|
|
100
|
-
case 'wordpress.org/themes':
|
|
101
|
-
resource = new CoreThemeResource(ref, progress);
|
|
102
|
-
break;
|
|
103
|
-
case 'wordpress.org/plugins':
|
|
104
|
-
resource = new CorePluginResource(ref, progress);
|
|
105
|
-
break;
|
|
106
|
-
case 'url':
|
|
107
|
-
resource = new UrlResource(ref, progress);
|
|
108
|
-
break;
|
|
109
|
-
default:
|
|
110
|
-
throw new Error(`Invalid resource: ${ref}`);
|
|
111
|
-
}
|
|
112
|
-
resource = new CachedResource(resource);
|
|
113
|
-
|
|
114
|
-
if (semaphore) {
|
|
115
|
-
resource = new SemaphoreResource(resource, semaphore);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return resource;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
setPlayground(playground: UniversalPHP) {
|
|
122
|
-
this.playground = playground;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Resolves the file contents
|
|
127
|
-
* @returns The resolved file.
|
|
128
|
-
*/
|
|
129
|
-
abstract resolve(): Promise<File>;
|
|
130
|
-
|
|
131
|
-
/** The name of the referenced file */
|
|
132
|
-
abstract get name(): string;
|
|
133
|
-
|
|
134
|
-
/** Whether this Resource is loaded asynchronously */
|
|
135
|
-
get isAsync(): boolean {
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* A `Resource` that represents a file in the VFS (virtual file system) of the playground.
|
|
141
|
-
*/
|
|
142
|
-
export class VFSResource extends Resource {
|
|
143
|
-
/**
|
|
144
|
-
* Creates a new instance of `VFSResource`.
|
|
145
|
-
* @param playground The playground client.
|
|
146
|
-
* @param resource The VFS reference.
|
|
147
|
-
* @param progress The progress tracker.
|
|
148
|
-
*/
|
|
149
|
-
constructor(
|
|
150
|
-
private resource: VFSReference,
|
|
151
|
-
public override progress?: ProgressTracker
|
|
152
|
-
) {
|
|
153
|
-
super();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/** @inheritDoc */
|
|
157
|
-
async resolve() {
|
|
158
|
-
const buffer = await this.playground!.readFileAsBuffer(
|
|
159
|
-
this.resource.path
|
|
160
|
-
);
|
|
161
|
-
this.progress?.set(100);
|
|
162
|
-
return new File([buffer], this.name);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/** @inheritDoc */
|
|
166
|
-
get name() {
|
|
167
|
-
return this.resource.path;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* A `Resource` that represents a literal file.
|
|
173
|
-
*/
|
|
174
|
-
export class LiteralResource extends Resource {
|
|
175
|
-
/**
|
|
176
|
-
* Creates a new instance of `LiteralResource`.
|
|
177
|
-
* @param resource The literal reference.
|
|
178
|
-
* @param progress The progress tracker.
|
|
179
|
-
*/
|
|
180
|
-
constructor(
|
|
181
|
-
private resource: LiteralReference,
|
|
182
|
-
public override progress?: ProgressTracker
|
|
183
|
-
) {
|
|
184
|
-
super();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/** @inheritDoc */
|
|
188
|
-
async resolve() {
|
|
189
|
-
this.progress?.set(100);
|
|
190
|
-
return new File([this.resource.contents], this.resource.name);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/** @inheritDoc */
|
|
194
|
-
get name() {
|
|
195
|
-
return this.resource.name;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* A base class for `Resource`s that require fetching data from a remote URL.
|
|
201
|
-
*/
|
|
202
|
-
export abstract class FetchResource extends Resource {
|
|
203
|
-
/**
|
|
204
|
-
* Creates a new instance of `FetchResource`.
|
|
205
|
-
* @param progress The progress tracker.
|
|
206
|
-
*/
|
|
207
|
-
constructor(public override progress?: ProgressTracker) {
|
|
208
|
-
super();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** @inheritDoc */
|
|
212
|
-
async resolve() {
|
|
213
|
-
this.progress?.setCaption(this.caption);
|
|
214
|
-
const url = this.getURL();
|
|
215
|
-
let response = await fetch(url);
|
|
216
|
-
response = await cloneResponseMonitorProgress(
|
|
217
|
-
response,
|
|
218
|
-
this.progress?.loadingListener ?? noop
|
|
219
|
-
);
|
|
220
|
-
if (response.status !== 200) {
|
|
221
|
-
throw new Error(`Could not download "${url}"`);
|
|
222
|
-
}
|
|
223
|
-
return new File([await response.blob()], this.name);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Gets the URL to fetch the data from.
|
|
228
|
-
* @returns The URL.
|
|
229
|
-
*/
|
|
230
|
-
protected abstract getURL(): string;
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Gets the caption for the progress tracker.
|
|
234
|
-
* @returns The caption.
|
|
235
|
-
*/
|
|
236
|
-
protected get caption() {
|
|
237
|
-
return `Downloading ${this.name}`;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/** @inheritDoc */
|
|
241
|
-
get name() {
|
|
242
|
-
try {
|
|
243
|
-
return new URL(this.getURL(), 'http://example.com').pathname
|
|
244
|
-
.split('/')
|
|
245
|
-
.pop()!;
|
|
246
|
-
} catch (e) {
|
|
247
|
-
return this.getURL();
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/** @inheritDoc */
|
|
252
|
-
override get isAsync(): boolean {
|
|
253
|
-
return true;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
258
|
-
const noop = (() => {}) as any;
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* A `Resource` that represents a file available from a URL.
|
|
262
|
-
*/
|
|
263
|
-
export class UrlResource extends FetchResource {
|
|
264
|
-
/**
|
|
265
|
-
* Creates a new instance of `UrlResource`.
|
|
266
|
-
* @param resource The URL reference.
|
|
267
|
-
* @param progress The progress tracker.
|
|
268
|
-
*/
|
|
269
|
-
constructor(private resource: UrlReference, progress?: ProgressTracker) {
|
|
270
|
-
super(progress);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/** @inheritDoc */
|
|
274
|
-
getURL() {
|
|
275
|
-
return this.resource.url;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/** @inheritDoc */
|
|
279
|
-
protected override get caption() {
|
|
280
|
-
return this.resource.caption ?? super.caption;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
let pluginProxyURL = 'https://playground.wordpress.net/plugin-proxy';
|
|
285
|
-
export function setPluginProxyURL(url: string) {
|
|
286
|
-
pluginProxyURL = url;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* A `Resource` that represents a WordPress core theme.
|
|
291
|
-
*/
|
|
292
|
-
export class CoreThemeResource extends FetchResource {
|
|
293
|
-
constructor(
|
|
294
|
-
private resource: CoreThemeReference,
|
|
295
|
-
progress?: ProgressTracker
|
|
296
|
-
) {
|
|
297
|
-
super(progress);
|
|
298
|
-
}
|
|
299
|
-
override get name() {
|
|
300
|
-
return zipNameToHumanName(this.resource.slug);
|
|
301
|
-
}
|
|
302
|
-
getURL() {
|
|
303
|
-
const zipName = toDirectoryZipName(this.resource.slug);
|
|
304
|
-
return `${pluginProxyURL}?theme=` + zipName;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* A resource that fetches a WordPress plugin from wordpress.org.
|
|
310
|
-
*/
|
|
311
|
-
export class CorePluginResource extends FetchResource {
|
|
312
|
-
constructor(
|
|
313
|
-
private resource: CorePluginReference,
|
|
314
|
-
progress?: ProgressTracker
|
|
315
|
-
) {
|
|
316
|
-
super(progress);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/** @inheritDoc */
|
|
320
|
-
override get name() {
|
|
321
|
-
return zipNameToHumanName(this.resource.slug);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/** @inheritDoc */
|
|
325
|
-
getURL() {
|
|
326
|
-
const zipName = toDirectoryZipName(this.resource.slug);
|
|
327
|
-
return `${pluginProxyURL}?plugin=` + zipName;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Transforms a plugin slug into a directory zip name.
|
|
333
|
-
* If the input already ends with ".zip", returns it unchanged.
|
|
334
|
-
* Otherwise, appends ".latest-stable.zip".
|
|
335
|
-
*/
|
|
336
|
-
export function toDirectoryZipName(rawInput: string) {
|
|
337
|
-
if (!rawInput) {
|
|
338
|
-
return rawInput;
|
|
339
|
-
}
|
|
340
|
-
if (rawInput.endsWith('.zip')) {
|
|
341
|
-
return rawInput;
|
|
342
|
-
}
|
|
343
|
-
return rawInput + '.latest-stable.zip';
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* A decorator for a resource that adds functionality such as progress tracking and caching.
|
|
348
|
-
*/
|
|
349
|
-
export class DecoratedResource<T extends Resource> extends Resource {
|
|
350
|
-
constructor(private resource: T) {
|
|
351
|
-
super();
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/** @inheritDoc */
|
|
355
|
-
async resolve() {
|
|
356
|
-
return this.resource.resolve();
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/** @inheritDoc */
|
|
360
|
-
override async setPlayground(playground: UniversalPHP) {
|
|
361
|
-
return this.resource.setPlayground(playground);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/** @inheritDoc */
|
|
365
|
-
get progress() {
|
|
366
|
-
return this.resource.progress;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/** @inheritDoc */
|
|
370
|
-
set progress(value) {
|
|
371
|
-
this.resource.progress = value;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/** @inheritDoc */
|
|
375
|
-
get name() {
|
|
376
|
-
return this.resource.name;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/** @inheritDoc */
|
|
380
|
-
override get isAsync() {
|
|
381
|
-
return this.resource.isAsync;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* A decorator for a resource that adds caching functionality.
|
|
387
|
-
*/
|
|
388
|
-
export class CachedResource<T extends Resource> extends DecoratedResource<T> {
|
|
389
|
-
protected override promise?: Promise<File>;
|
|
390
|
-
|
|
391
|
-
/** @inheritDoc */
|
|
392
|
-
override async resolve() {
|
|
393
|
-
if (!this.promise) {
|
|
394
|
-
this.promise = super.resolve();
|
|
395
|
-
}
|
|
396
|
-
return this.promise;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* A decorator for a resource that adds concurrency control functionality through a semaphore.
|
|
402
|
-
*/
|
|
403
|
-
export class SemaphoreResource<
|
|
404
|
-
T extends Resource
|
|
405
|
-
> extends DecoratedResource<T> {
|
|
406
|
-
constructor(resource: T, private readonly semaphore: Semaphore) {
|
|
407
|
-
super(resource);
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/** @inheritDoc */
|
|
411
|
-
override async resolve() {
|
|
412
|
-
if (!this.isAsync) {
|
|
413
|
-
return super.resolve();
|
|
414
|
-
}
|
|
415
|
-
return this.semaphore.run(() => super.resolve());
|
|
416
|
-
}
|
|
417
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { StepHandler } from '.';
|
|
2
|
-
import { asDOM } from './common';
|
|
3
|
-
|
|
4
|
-
export interface ActivatePluginStep {
|
|
5
|
-
step: 'activatePlugin';
|
|
6
|
-
plugin: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Activates a WordPress plugin in the Playground.
|
|
11
|
-
*
|
|
12
|
-
* @param playground The playground client.
|
|
13
|
-
* @param plugin The plugin slug.
|
|
14
|
-
*/
|
|
15
|
-
export const activatePlugin: StepHandler<ActivatePluginStep> = async (
|
|
16
|
-
playground,
|
|
17
|
-
{ plugin },
|
|
18
|
-
progress
|
|
19
|
-
) => {
|
|
20
|
-
progress?.tracker.setCaption(`Activating ${plugin}`);
|
|
21
|
-
const pluginsPage = asDOM(
|
|
22
|
-
await playground.request({
|
|
23
|
-
url: '/wp-admin/plugins.php',
|
|
24
|
-
})
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
const link = pluginsPage.querySelector(
|
|
28
|
-
`tr[data-slug="${plugin}"] a`
|
|
29
|
-
)! as HTMLAnchorElement;
|
|
30
|
-
const href = link.attributes.getNamedItem('href')!.value;
|
|
31
|
-
|
|
32
|
-
await playground.request({
|
|
33
|
-
url: '/wp-admin/' + href,
|
|
34
|
-
});
|
|
35
|
-
};
|