@@ -7,8 +7,9 @@ import { existsSync } from "node:fs"
77import { createServer as createHttpServer , type Server as HttpServer } from "node:http"
88import { mkdir , readFile , rename , rm , stat , unlink , writeFile } from "node:fs/promises"
99import { homedir } from "node:os"
10- import { basename , join } from "node:path"
10+ import { basename , dirname , join } from "node:path"
1111import { createServer as createNetServer } from "node:net"
12+ import * as PlaygroundStorage from "@wp-playground/storage"
1213import { resolveWordPressRelease } from "@wp-playground/wordpress"
1314
1415export interface PlaygroundCliModule {
@@ -103,7 +104,7 @@ export async function startPlaygroundCliServer(spec: RuntimeCreateSpec, mounts:
103104 wp : localAssetServer ?. url ?? wordpressStartupAsset ?. wp ,
104105 php : spec . environment . phpVersion ,
105106 "site-url" : spec . preview ?. siteUrl ,
106- blueprint : playgroundBlueprint ( spec . environment . blueprint , spec . policy , spec . preview ?. siteUrl ) ,
107+ blueprint : playgroundCliBlueprint ( spec ) ,
107108 } )
108109 } finally {
109110 await localAssetServer ?. close ( )
@@ -135,6 +136,49 @@ export async function startPlaygroundCliServer(spec: RuntimeCreateSpec, mounts:
135136 }
136137}
137138
139+ function playgroundCliBlueprint ( spec : RuntimeCreateSpec ) : unknown {
140+ const blueprint = playgroundBlueprint ( spec . environment . blueprint , spec . policy , spec . preview ?. siteUrl )
141+ if ( blueprint !== spec . environment . blueprint ) {
142+ return blueprint
143+ }
144+
145+ return localBlueprintPackageFilesystem ( spec ) ?? blueprint
146+ }
147+
148+ function localBlueprintPackageFilesystem ( spec : RuntimeCreateSpec ) : LocalBlueprintPackageFilesystem | undefined {
149+ const task = spec . metadata ?. task
150+ if ( ! task || typeof task !== "object" || Array . isArray ( task ) ) {
151+ return undefined
152+ }
153+
154+ const blueprintPath = ( task as Record < string , unknown > ) . blueprintPath
155+ if ( typeof blueprintPath !== "string" || blueprintPath . length === 0 ) {
156+ return undefined
157+ }
158+
159+ return new LocalBlueprintPackageFilesystem ( blueprintPath )
160+ }
161+
162+ class LocalBlueprintPackageFilesystem {
163+ private readonly filesystem : ReadableBlueprintFilesystem
164+ private readonly blueprintFileName : string
165+
166+ constructor ( blueprintPath : string ) {
167+ const NodeJsFilesystem = ( PlaygroundStorage as unknown as { NodeJsFilesystem : new ( root : string ) => ReadableBlueprintFilesystem } ) . NodeJsFilesystem
168+ this . filesystem = new NodeJsFilesystem ( dirname ( blueprintPath ) )
169+ this . blueprintFileName = basename ( blueprintPath )
170+ }
171+
172+ read ( path : string ) : ReturnType < ReadableBlueprintFilesystem [ "read" ] > {
173+ const normalizedPath = path . replace ( / \\ / g, "/" ) . replace ( / ^ \/ + / , "" )
174+ return this . filesystem . read ( normalizedPath === "blueprint.json" ? this . blueprintFileName : normalizedPath )
175+ }
176+ }
177+
178+ interface ReadableBlueprintFilesystem {
179+ read ( path : string ) : Promise < unknown >
180+ }
181+
138182async function startPlaygroundCliWithDynamicPortRetry ( callback : ( port : number ) => Promise < PlaygroundCliServer > , fixedPreviewPort : boolean ) : Promise < PlaygroundCliServer > {
139183 const attempts = fixedPreviewPort ? 1 : 6
140184 for ( let attempt = 1 ; attempt <= attempts ; attempt ++ ) {
0 commit comments