@@ -18,12 +18,13 @@ const STATION_SCRIPT_HINTS = {
1818
1919function printUsage ( ) {
2020 console . log ( `Usage:
21- node packages/create-apiops/bin/method-cli.js start [--locale <locale>] [--json] [--list] [--answers <yes,no,...>] [--next-action <resources|canvases|exit>]
21+ node packages/create-apiops/bin/method-cli.js start [--locale <locale>] [--default-locale <locale>] [-- json] [--list] [--answers <yes,no,...>] [--next-action <resources|canvases|exit>]
2222 node packages/create-apiops/bin/method-cli.js resources --station <station-id> [--locale <locale>] [--style <style>] [--json] [--list] [--step-actions <details,next,...>]
2323 node packages/create-apiops/bin/method-cli.js generate-canvases [--station <station-id> | --stations <ids> | --preset new-api] [--locale <locale>] [--style <style>] [--output <dir>] [--force] [--json]
2424
2525Examples:
2626 node packages/create-apiops/bin/method-cli.js start --locale en
27+ node packages/create-apiops/bin/method-cli.js start --default-locale en
2728 node packages/create-apiops/bin/method-cli.js start --locale en --answers yes,no,yes --next-action resources
2829 node packages/create-apiops/bin/method-cli.js resources --station api-product-strategy --locale en
2930 node packages/create-apiops/bin/method-cli.js generate-canvases --preset new-api --style REST --output ./specs/canvases
@@ -71,6 +72,14 @@ function readJson(filePath) {
7172 return JSON . parse ( fs . readFileSync ( filePath , "utf8" ) ) ;
7273}
7374
75+ function runCommand ( command , args , options = { } ) {
76+ return spawnSync ( command , args , {
77+ encoding : "utf8" ,
78+ shell : false ,
79+ ...options
80+ } ) ;
81+ }
82+
7483function getNextStepHints ( stationId ) {
7584 const hints = STATION_SCRIPT_HINTS [ stationId ] ;
7685 if ( hints ) {
@@ -155,44 +164,137 @@ async function fillCanvasSectionsInteractive(stationId, step, locale, output, rl
155164}
156165
157166function resolveCanvasExportCommand ( ) {
158- const binPath = path . resolve (
159- process . cwd ( ) ,
160- "node_modules" ,
161- ".bin" ,
162- process . platform === "win32" ? "canvascreator-export.cmd" : "canvascreator-export"
163- ) ;
164- if ( fs . existsSync ( binPath ) ) {
167+ const packageRoot = path . resolve ( process . cwd ( ) , "node_modules" , "canvascreator" ) ;
168+ if ( ! fs . existsSync ( packageRoot ) ) {
165169 return {
166- command : binPath ,
167- args : [ ]
170+ ok : false ,
171+ reason : "SVG export requires CanvasCreator export support, which is not installed in this project." ,
172+ help : "Run `npm install` to install project dependencies, or `npm install canvascreator` to add CanvasCreator manually."
168173 } ;
169174 }
170175
171- const scriptPath = path . resolve ( process . cwd ( ) , "node_modules" , "canvascreator" , "scripts" , "export.js" ) ;
176+ const packageJsonPath = path . join ( packageRoot , "package.json" ) ;
177+ if ( fs . existsSync ( packageJsonPath ) ) {
178+ const packageJson = readJson ( packageJsonPath ) ;
179+ const binEntry = typeof packageJson . bin === "string"
180+ ? packageJson . bin
181+ : packageJson . bin ?. [ "canvascreator-export" ] ;
182+
183+ if ( binEntry ) {
184+ const binPath = path . resolve ( packageRoot , binEntry ) ;
185+ if ( fs . existsSync ( binPath ) ) {
186+ return {
187+ ok : true ,
188+ command : process . execPath ,
189+ args : [ binPath ]
190+ } ;
191+ }
192+ }
193+ }
194+
195+ const scriptPath = path . resolve ( packageRoot , "scripts" , "export.js" ) ;
172196 if ( fs . existsSync ( scriptPath ) ) {
173197 return {
198+ ok : true ,
174199 command : process . execPath ,
175200 args : [ scriptPath ]
176201 } ;
177202 }
178203
179- return null ;
204+ return {
205+ ok : false ,
206+ reason : "CanvasCreator is installed, but its export CLI could not be found." ,
207+ help : "Reinstall `canvascreator` or use the CanvasCreator web app to export SVG from the JSON file."
208+ } ;
209+ }
210+
211+ function resolveStartLocale ( options = { } ) {
212+ const explicitLocale = options . locale ;
213+ const defaultLocale = options [ "default-locale" ] || methodEngine . DEFAULT_LOCALE ;
214+ if ( explicitLocale ) {
215+ return explicitLocale ;
216+ }
217+
218+ return methodEngine . getSupportedMethodLocales ( ) . includes ( defaultLocale )
219+ ? defaultLocale
220+ : methodEngine . DEFAULT_LOCALE ;
221+ }
222+
223+ async function maybePromptForStartLocale ( options = { } ) {
224+ const selectedLocale = resolveStartLocale ( options ) ;
225+ if (
226+ options . locale ||
227+ options . json ||
228+ options . list ||
229+ options . answers ||
230+ ! process . stdin . isTTY
231+ ) {
232+ return selectedLocale ;
233+ }
234+
235+ const supportedLocales = methodEngine . getSupportedMethodLocales ( ) ;
236+ const rl = readline . createInterface ( {
237+ input : process . stdin ,
238+ output : process . stdout
239+ } ) ;
240+
241+ try {
242+ console . log ( `Default method language: ${ selectedLocale } ` ) ;
243+ console . log ( `Available languages: ${ supportedLocales . join ( ", " ) } ` ) ;
244+ const answer = ( await rl . question ( "Press Enter to keep the default, or type another locale for this run: " ) )
245+ . trim ( )
246+ . toLowerCase ( ) ;
247+ if ( ! answer ) {
248+ console . log ( "" ) ;
249+ return selectedLocale ;
250+ }
251+
252+ if ( supportedLocales . includes ( answer ) ) {
253+ console . log ( "" ) ;
254+ return answer ;
255+ }
256+
257+ console . log ( `Unknown locale "${ answer } ", using ${ selectedLocale } .` ) ;
258+ console . log ( "" ) ;
259+ return selectedLocale ;
260+ } finally {
261+ rl . close ( ) ;
262+ }
263+ }
264+
265+ function formatCommandFailure ( result ) {
266+ if ( result . error ?. message ) {
267+ return result . error . message ;
268+ }
269+
270+ const stderr = String ( result . stderr || "" ) . trim ( ) ;
271+ if ( stderr ) {
272+ return stderr ;
273+ }
274+
275+ const stdout = String ( result . stdout || "" ) . trim ( ) ;
276+ if ( stdout ) {
277+ return stdout ;
278+ }
279+
280+ return "Canvas export failed." ;
180281}
181282
182283function exportCanvasSvgForResource ( stationId , step , locale , output ) {
183284 const jsonPath = methodEngine . generateCanvasForStationResource ( stationId , step . resourceId , locale , output ) ;
184285 const exportCommand = resolveCanvasExportCommand ( ) ;
185- if ( ! exportCommand ) {
286+ if ( ! exportCommand . ok ) {
186287 return {
187288 ok : false ,
188- reason : "CanvasCreator export CLI is not installed in this project yet." ,
289+ reason : exportCommand . reason ,
290+ help : exportCommand . help ,
189291 jsonPath
190292 } ;
191293 }
192294
193295 const outputDir = path . dirname ( jsonPath ) ;
194296 const outputFile = path . join ( outputDir , `${ step . resourceId } .svg` ) ;
195- const result = spawnSync (
297+ const result = runCommand (
196298 exportCommand . command ,
197299 [
198300 ...exportCommand . args ,
@@ -201,16 +303,14 @@ function exportCanvasSvgForResource(stationId, step, locale, output) {
201303 "--output" , outputFile
202304 ] ,
203305 {
204- cwd : process . cwd ( ) ,
205- encoding : "utf8" ,
206- shell : process . platform === "win32"
306+ cwd : process . cwd ( )
207307 }
208308 ) ;
209309
210310 if ( result . status !== 0 ) {
211311 return {
212312 ok : false ,
213- reason : result . stderr || result . stdout || "Canvas export failed." ,
313+ reason : formatCommandFailure ( result ) ,
214314 jsonPath
215315 } ;
216316 }
@@ -562,6 +662,9 @@ async function runInteractiveResources(options) {
562662 console . log ( `Source JSON: ${ exportResult . jsonPath } ` ) ;
563663 } else {
564664 console . log ( `SVG export unavailable: ${ exportResult . reason } ` ) ;
665+ if ( exportResult . help ) {
666+ console . log ( exportResult . help ) ;
667+ }
565668 console . log ( `Canvas JSON is still available at: ${ exportResult . jsonPath } ` ) ;
566669 console . log ( `CanvasCreator URL: ${ methodEngine . getCanvasCreatorUrl ( step . canvasId , locale ) } ` ) ;
567670 }
@@ -627,7 +730,8 @@ async function main() {
627730 }
628731
629732 if ( command === "start" ) {
630- const data = methodEngine . buildStartData ( options . locale || methodEngine . DEFAULT_LOCALE ) ;
733+ const locale = await maybePromptForStartLocale ( options ) ;
734+ const data = methodEngine . buildStartData ( locale ) ;
631735 if ( options . json ) {
632736 console . log ( JSON . stringify ( data , null , 2 ) ) ;
633737 return ;
@@ -638,7 +742,7 @@ async function main() {
638742 return ;
639743 }
640744
641- await runInteractiveStart ( data , options ) ;
745+ await runInteractiveStart ( data , { ... options , locale } ) ;
642746 return ;
643747 }
644748
0 commit comments