@joystick.js/cli-canary 0.0.0-canary.2137 → 0.0.0-canary.2139

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.
@@ -1,5 +1,5 @@
1
- import _ from"chalk";import N from"child_process";import $ from"fs";import"os";import v,{dirname as j}from"path";import{fileURLToPath as R}from"url";import I from"util";import m from"./check_if_port_occupied.js";import i from"../cli_log.js";import l from"./get_database_process_ids.js";import H from"../get_platform_safe_path.js";import u from"../kill_port_process.js";import g from"../load_settings.js";import V from"../loader.js";import d from"../path_exists.js";import O from"../required_files.js";import C from"./start_app_server.js";import M from"./start_databases.js";import A from"./start_hmr_server.js";import P from"./watch_for_changes/index.js";import q from"../constants.js";import x from"./kill_process_ids.js";import L,{run_tests_integrated as b}from"./run_tests.js";import G from"../debounce.js";import J from"./databases/download_database_binary.js";const{stat:U}=$.promises,F=I.promisify(N.exec),n=parseInt(process?.version?.split(".")[0]?.replace("v",""),10),B=R(import.meta.url),p=j(B),f=[];let y=null,w=!1,h=!1;const k=async()=>{w&&h&&setTimeout(async()=>{console.log("Running tests...");try{await b({__dirname:p})}catch(s){console.error("Error running integrated tests:",s)}},2e3)},S=async(s={})=>{await m(1977)&&await u(1977),setTimeout(async()=>{try{await D({environment:"test",port:1977,watch:!1,imports:s?.imports||[],_is_test_server:!0})}catch(r){console.error("Error starting test server:",r)}},100)},z=()=>{y&&(y.kill(),y=null),h=!1},X=()=>{w=!1,h=!1},Vs=async(s=!1)=>{const t=l();await L({watch:s,__dirname:p,process_ids:[...f,...t],cleanup_process:process.cleanup_process})},K=(s=[],t=0,r="")=>{const c=["--no-warnings"];t<19&&c.push("--experimental-specifier-resolution=node");const e=N.fork(v.resolve(`${r}/cleanup.js`),[],{detached:!0,silent:!0});process.cleanup_process=e,process.on("SIGINT",async()=>{const o=l();e.send(JSON.stringify({process_ids:[...s,...o]})),process.exit()}),process.on("SIGTERM",async()=>{const o=l();e.send(JSON.stringify({process_ids:[...s,...o]})),process.exit()})},Q=async(s=[])=>{const t=s?.find(a=>a?.path?.match(q.SETTINGS_FILE_NAME_REGEX)?.length>0),r=s?.find(a=>a?.path?.includes("i18n")),c=s?.find(a=>a?.path?.includes("index.html")),e=s?.find(a=>a?.path?.includes("index.css")||a?.path?.includes("css/")),o=s?.find(a=>a?.path?.includes("index.client.js"));process.hmr_server_process.send(JSON.stringify({type:"FILE_CHANGE",settings:t?await g(process.env.NODE_ENV):null,i18n_change:!!r,index_html_change:!!c,index_css_change:!!e,index_client_change:!!o}))},W=(s=0,t=!1,r={},c=[],e=!1)=>{process.hmr_server_process.on("message",async o=>{["HAS_HMR_CONNECTIONS","HAS_NO_HMR_CONNECTIONS","HMR_UPDATE_COMPLETE"].includes(o?.type)||process.loader.print(o),o?.type==="HAS_HMR_CONNECTIONS"&&(process.hmr_server_process.has_connections=!0),o?.type==="HAS_NO_HMR_CONNECTIONS"&&(process.hmr_server_process.has_connections=!1),o?.type==="HMR_UPDATE_COMPLETE"&&process.app_server_process&&!process.app_server_restarting&&(process.app_server_restarting=!0,T(s,t,r,c,e))})},Y=()=>{process.hmr_server_process.on("error",s=>{i(s.toString(),{level:"danger",docs:"https://github.com/cheatcode/joystick"})}),process.hmr_server_process.stdout.on("data",s=>{console.log(s.toString())}),process.hmr_server_process.stderr.on("data",s=>{i(s.toString(),{level:"danger",docs:"https://github.com/cheatcode/joystick"})})},Z=(s=0,t="",r=!1,c={},e=[],o=!1)=>{process.hmr_server_process=A(s,t),f.push(process.hmr_server_process?.pid),Y(),W(s,r,c,e,o)},ss=async(s={})=>{const t=await g(process.env.NODE_ENV),r=t?.config?.databases?JSON.stringify(t?.config?.databases):"",c=s?.config?.databases?JSON.stringify(s?.config?.databases):"";return r!==c},T=async(s=0,t=!1,r=null,c=[],e=!1)=>{G(async()=>{if(await ss(r)){const a=l();i(`Database configuration has changed in settings.${process.env.NODE_ENV}.json. Please restart your app to add, change, or remove databases.`,{level:"danger",docs:"https://cheatcode.co/docs/joystick/structure"}),x([process.hmr_server_process?.pid,process.app_server_process?.pid,...a]),process.exit(0)}else e&&(X(),z()),x([...process.app_server_process.external_process_ids||[]]),await u(process.env.PORT),E(s,t,c,e),e&&await S({imports:c||[]})},300)},es=(s=!1,t=!1,r=!1)=>{process.app_server_process.external_process_ids=[],process.app_server_process.on("message",c=>{c?.external_process_id&&(process.app_server_process.external_process_ids=[...process.app_server_process.external_process_ids||[],c?.external_process_id])}),process.app_server_process.on("error",c=>{r||i(c.toString(),{level:"danger",docs:"https://github.com/cheatcode/joystick"})}),process.app_server_process.stdout.on("data",async c=>{const e=c.toString(),o=e.includes("App running at:");r||(e&&o&&process.env.NODE_ENV!=="test"&&process.loader.print(e),e&&!o&&!e.includes("BUILD_ERROR")&&console.log(e),e&&o&&process.env.NODE_ENV,e&&o&&t&&process.env.NODE_ENV!=="test"&&(w=!0,k()),e&&o&&process.env.NODE_ENV==="test"&&(h=!0,k()))}),process.app_server_process.stderr.on("data",c=>{r||i(c.toString(),{level:"danger",docs:"https://cheatcode.co/docs/joystick"})})},E=(s=0,t=!1,r=[],c=!1,e=!1)=>{process.app_server_process=C(s,t,r),f.push(process.app_server_process?.pid),es(t,c,e),process.app_server_restarting=!1},ts=async(s={})=>{const t=s?.config?.databases?.map((r={})=>r?.provider);for(let r=0;r<t?.length;r+=1){const c=t[r];await J(c)}},rs=(s={},t=2600)=>{process.title=s?.environment==="test"?"joystick_test":"joystick",process.project_folder=v.basename(process.cwd()),process.loader=new V,s?.environment==="test"&&(console.log(""),process.loader.print(`Initializing test environment...
2
- `)),process.env.LOGS_PATH=s?.logs||null,process.env.NODE_ENV=s?.environment||"development",process.env.PORT=t,process.env.IS_DEBUG_MODE=s?.debug},cs=(s=2600)=>{i(`Port ${s} is already occupied. To start Joystick on this port, clear it and try again.`,{level:"danger"}),process.exit(0)},os=(s=2600)=>parseInt(s||2600,10),as=async()=>{const s=H(`${process.cwd()}/.joystick/build`);await d(s)&&await F(`${process.platform==="win32"?"rmdir /s /q":"rm -rf"} ${s}`)},is=async()=>{const s=[];for(let t=0;t<O?.length;t+=1){const r=O[t],c=await d(`${process.cwd()}/${r.path}`),e=c&&await U(`${process.cwd()}/${r.path}`);r&&r.type==="file"&&(!c||c&&!e.isFile())&&s.push({type:"file",path:r.path}),r&&r.type==="directory"&&(!c||c&&!e.isDirectory())&&s.push({type:"directory",path:r.path})}if(s?.length>0){const t=s?.filter(e=>e.type==="file"),r=s?.filter(e=>e.type==="directory");let c=`The following paths are missing and required in a Joystick project:
1
+ import _ from"chalk";import y from"child_process";import b from"fs";import"os";import w,{dirname as k}from"path";import{fileURLToPath as S}from"url";import T from"util";import f from"./check_if_port_occupied.js";import i from"../cli_log.js";import d from"./get_database_process_ids.js";import D from"../get_platform_safe_path.js";import m from"../kill_port_process.js";import g from"../load_settings.js";import $ from"../loader.js";import l from"../path_exists.js";import E from"../required_files.js";import j from"./start_app_server.js";import R from"./start_databases.js";import I from"./start_hmr_server.js";import H from"./watch_for_changes/index.js";import C from"../constants.js";import N from"./kill_process_ids.js";import M,{run_tests_integrated as v}from"./run_tests.js";import V from"../debounce.js";import A from"./databases/download_database_binary.js";const{stat:P}=b.promises,q=T.promisify(y.exec),n=parseInt(process?.version?.split(".")[0]?.replace("v",""),10),L=S(import.meta.url),p=k(L),h=[],G=async(s=!1)=>{const t=d();await M({watch:s,__dirname:p,process_ids:[...h,...t],cleanup_process:process.cleanup_process})},J=(s=[],t=0,r="")=>{const c=["--no-warnings"];t<19&&c.push("--experimental-specifier-resolution=node");const e=y.fork(w.resolve(`${r}/cleanup.js`),[],{detached:!0,silent:!0});process.cleanup_process=e,process.on("SIGINT",async()=>{const o=d();e.send(JSON.stringify({process_ids:[...s,...o]})),process.exit()}),process.on("SIGTERM",async()=>{const o=d();e.send(JSON.stringify({process_ids:[...s,...o]})),process.exit()})},U=async(s=[])=>{const t=s?.find(a=>a?.path?.match(C.SETTINGS_FILE_NAME_REGEX)?.length>0),r=s?.find(a=>a?.path?.includes("i18n")),c=s?.find(a=>a?.path?.includes("index.html")),e=s?.find(a=>a?.path?.includes("index.css")||a?.path?.includes("css/")),o=s?.find(a=>a?.path?.includes("index.client.js"));process.hmr_server_process.send(JSON.stringify({type:"FILE_CHANGE",settings:t?await g(process.env.NODE_ENV):null,i18n_change:!!r,index_html_change:!!c,index_css_change:!!e,index_client_change:!!o}))},F=(s=0,t=!1,r={},c=[],e=!1)=>{process.hmr_server_process.on("message",async o=>{["HAS_HMR_CONNECTIONS","HAS_NO_HMR_CONNECTIONS","HMR_UPDATE_COMPLETE"].includes(o?.type)||process.loader.print(o),o?.type==="HAS_HMR_CONNECTIONS"&&(process.hmr_server_process.has_connections=!0),o?.type==="HAS_NO_HMR_CONNECTIONS"&&(process.hmr_server_process.has_connections=!1),o?.type==="HMR_UPDATE_COMPLETE"&&process.app_server_process&&!process.app_server_restarting&&(process.app_server_restarting=!0,O(s,t,r,c,e))})},B=()=>{process.hmr_server_process.on("error",s=>{i(s.toString(),{level:"danger",docs:"https://github.com/cheatcode/joystick"})}),process.hmr_server_process.stdout.on("data",s=>{console.log(s.toString())}),process.hmr_server_process.stderr.on("data",s=>{i(s.toString(),{level:"danger",docs:"https://github.com/cheatcode/joystick"})})},z=(s=0,t="",r=!1,c={},e=[],o=!1)=>{process.hmr_server_process=I(s,t),h.push(process.hmr_server_process?.pid),B(),F(s,r,c,e,o)},X=async(s={})=>{const t=await g(process.env.NODE_ENV),r=t?.config?.databases?JSON.stringify(t?.config?.databases):"",c=s?.config?.databases?JSON.stringify(s?.config?.databases):"";return r!==c},O=async(s=0,t=!1,r=null,c=[],e=!1)=>{V(async()=>{if(await X(r)){const a=d();i(`Database configuration has changed in settings.${process.env.NODE_ENV}.json. Please restart your app to add, change, or remove databases.`,{level:"danger",docs:"https://cheatcode.co/docs/joystick/structure"}),N([process.hmr_server_process?.pid,process.app_server_process?.pid,...a]),process.exit(0)}else N([...process.app_server_process.external_process_ids||[]]),await m(process.env.PORT),u(s,t,c,e)},300)},K=(s=!1,t=!1,r=!1)=>{process.app_server_process.external_process_ids=[],process.app_server_process.on("message",c=>{c?.external_process_id&&(process.app_server_process.external_process_ids=[...process.app_server_process.external_process_ids||[],c?.external_process_id])}),process.app_server_process.on("error",c=>{r||i(c.toString(),{level:"danger",docs:"https://github.com/cheatcode/joystick"})}),process.app_server_process.stdout.on("data",async c=>{const e=c.toString(),o=e.includes("App running at:");r||(e&&o&&process.env.NODE_ENV!=="test"&&process.loader.print(e),e&&!o&&!e.includes("BUILD_ERROR")&&console.log(e),e&&o&&process.env.NODE_ENV==="test"&&G(s),e&&o&&t&&process.env.NODE_ENV!=="test"&&setTimeout(async()=>{try{await v({__dirname:p})}catch(a){console.error("Error running integrated tests:",a)}},2e3))}),process.app_server_process.stderr.on("data",c=>{r||i(c.toString(),{level:"danger",docs:"https://cheatcode.co/docs/joystick"})})},u=(s=0,t=!1,r=[],c=!1,e=!1)=>{process.app_server_process=j(s,t,r),h.push(process.app_server_process?.pid),K(t,c,e),process.app_server_restarting=!1},Q=async(s={})=>{const t=s?.config?.databases?.map((r={})=>r?.provider);for(let r=0;r<t?.length;r+=1){const c=t[r];await A(c)}},W=(s={},t=2600)=>{process.title=s?.environment==="test"?"joystick_test":"joystick",process.project_folder=w.basename(process.cwd()),process.loader=new $,s?.environment==="test"&&(console.log(""),process.loader.print(`Initializing test environment...
2
+ `)),process.env.LOGS_PATH=s?.logs||null,process.env.NODE_ENV=s?.environment||"development",process.env.PORT=t,process.env.IS_DEBUG_MODE=s?.debug},Y=(s=2600)=>{i(`Port ${s} is already occupied. To start Joystick on this port, clear it and try again.`,{level:"danger"}),process.exit(0)},Z=(s=2600)=>parseInt(s||2600,10),ss=async()=>{const s=D(`${process.cwd()}/.joystick/build`);await l(s)&&await q(`${process.platform==="win32"?"rmdir /s /q":"rm -rf"} ${s}`)},es=async()=>{const s=[];for(let t=0;t<E?.length;t+=1){const r=E[t],c=await l(`${process.cwd()}/${r.path}`),e=c&&await P(`${process.cwd()}/${r.path}`);r&&r.type==="file"&&(!c||c&&!e.isFile())&&s.push({type:"file",path:r.path}),r&&r.type==="directory"&&(!c||c&&!e.isDirectory())&&s.push({type:"directory",path:r.path})}if(s?.length>0){const t=s?.filter(e=>e.type==="file"),r=s?.filter(e=>e.type==="directory");let c=`The following paths are missing and required in a Joystick project:
3
3
 
4
4
  `;if(t?.length>0){c+=` ${_.yellow(">")} Required Files:
5
5
 
@@ -8,5 +8,5 @@ ${a&&r?.length>0?`
8
8
  `:""}`)}`}}if(r?.length>0){c+=` ${_.yellow(">")} Required Directories:
9
9
 
10
10
  `;for(let e=0;e<r?.length;e+=1){const o=r[e];c+=` ${_.red(`/${o.path}
11
- `)}`}}i(c,{level:"danger",docs:"https://cheatcode.co/docs/joystick/structure"}),process.exit(0)}},ns=async()=>{const s=await d(`${process.cwd()}/.joystick`),t=await d(`${process.cwd()}/tests`);process.env.NODE_ENV==="test"&&(!s||!t)&&(i("joystick test must be run in a directory with a .joystick folder and tests folder.",{level:"danger",docs:"https://cheatcode.co/docs/joystick/cli/test"}),process.exit(0)),process.env.NODE_ENV!=="test"&&!s&&(i("joystick start must be run in a directory with a .joystick folder.",{level:"danger",docs:"https://cheatcode.co/docs/joystick/cli/start"}),process.exit(0))},D=async(s={})=>{await ns(),await is(),await as();const t=os(s?.port),r=await m(t),c=await m(t+1);r&&cs(t),c&&u(t),rs(s,t);const e=await g(process.env.NODE_ENV);await ts(e),await M({environment:process.env.NODE_ENV,port:t,settings:e}),s?.tests&&s?.environment!=="test"&&!s?._is_test_server&&await S({imports:s?.imports||[]}),s?._is_test_server?E(n,!1,s?.imports||[],!1,!0):P({hot_module_reload:(o=[])=>Q(o),restart_app_server:()=>T(n,s?.watch,e,s?.imports,s?.tests),start_app_server:()=>E(n,s?.watch,s?.imports,s?.tests,s?._is_test_server),start_hmr_server:s?.environment!=="test"?()=>Z(n,p,s?.watch,e,s?.imports,s?.tests):null,run_tests:s?.tests?async()=>{setTimeout(async()=>{try{await b({__dirname:p})}catch(o){console.error("Error running tests after file change:",o)}},1e3)}:null},{excluded_paths:e?.config?.build?.excluded_paths,custom_copy_paths:e?.config?.build?.copy_paths?.map(o=>({path:o}))||[]}),K(f,n,p)};var Cs=D;export{Cs as default};
11
+ `)}`}}i(c,{level:"danger",docs:"https://cheatcode.co/docs/joystick/structure"}),process.exit(0)}},ts=async()=>{const s=await l(`${process.cwd()}/.joystick`),t=await l(`${process.cwd()}/tests`);process.env.NODE_ENV==="test"&&(!s||!t)&&(i("joystick test must be run in a directory with a .joystick folder and tests folder.",{level:"danger",docs:"https://cheatcode.co/docs/joystick/cli/test"}),process.exit(0)),process.env.NODE_ENV!=="test"&&!s&&(i("joystick start must be run in a directory with a .joystick folder.",{level:"danger",docs:"https://cheatcode.co/docs/joystick/cli/start"}),process.exit(0))},x=async(s={})=>{await ts(),await es(),await ss();const t=Z(s?.port),r=await f(t),c=await f(t+1);r&&Y(t),c&&m(t),W(s,t);const e=await g(process.env.NODE_ENV);await Q(e),await R({environment:process.env.NODE_ENV,port:t,settings:e}),s?.tests&&s?.environment!=="test"&&(await f(1977)&&await m(1977),setTimeout(async()=>{try{await x({environment:"test",port:1977,watch:!1,imports:s?.imports||[],_is_test_server:!0})}catch(a){console.error("Error starting test server:",a)}},100)),s?._is_test_server?u(n,!1,s?.imports||[],!1,!0):H({hot_module_reload:(o=[])=>U(o),restart_app_server:()=>O(n,s?.watch,e,s?.imports,s?.tests),start_app_server:()=>u(n,s?.watch,s?.imports,s?.tests,s?._is_test_server),start_hmr_server:s?.environment!=="test"?()=>z(n,p,s?.watch,e,s?.imports,s?.tests):null,run_tests:s?.tests?async()=>{setTimeout(async()=>{try{await v({__dirname:p})}catch(o){console.error("Error running tests after file change:",o)}},1e3)}:null},{excluded_paths:e?.config?.build?.excluded_paths,custom_copy_paths:e?.config?.build?.copy_paths?.map(o=>({path:o}))||[]}),J(h,n,p)};var Ds=x;export{Ds as default};
12
12
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/development_server/index.js"],
4
- "sourcesContent": ["import chalk from 'chalk';\nimport child_process from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path, { dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport util from 'util';\nimport check_if_port_occupied from './check_if_port_occupied.js';\nimport cli_log from '../cli_log.js';\nimport get_database_process_ids from './get_database_process_ids.js';\n import get_platform_safe_path from '../get_platform_safe_path.js';\nimport kill_port_process from '../kill_port_process.js';\nimport load_settings from '../load_settings.js';\nimport Loader from '../loader.js';\nimport path_exists from '../path_exists.js';\nimport required_files from '../required_files.js';\nimport start_app_server from './start_app_server.js';\nimport start_databases from './start_databases.js';\nimport start_hmr_server from './start_hmr_server.js';\nimport watch_for_changes from './watch_for_changes/index.js';\nimport constants from '../constants.js';\nimport kill_process_ids from './kill_process_ids.js';\nimport run_tests, { run_tests_integrated } from './run_tests.js';\nimport debounce from '../debounce.js';\nimport download_database_binary from './databases/download_database_binary.js';\n\nconst { stat } = fs.promises;\nconst exec = util.promisify(child_process.exec);\n\nconst node_major_version = parseInt(\n process?.version?.split(\".\")[0]?.replace(\"v\", \"\"),\n 10\n);\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst process_ids = [];\n\n// NOTE: Global test server process tracking and server readiness state\nlet test_server_process = null;\nlet main_server_ready = false;\nlet test_server_ready = false;\n\nconst check_and_run_tests = async () => {\n if (main_server_ready && test_server_ready) {\n // NOTE: Add 2s delay to ensure both servers are fully ready\n setTimeout(async () => {\n console.log('Running tests...');\n try {\n await run_tests_integrated({\n __dirname,\n });\n } catch (error) {\n console.error('Error running integrated tests:', error);\n }\n }, 2000);\n }\n};\n\nconst start_test_server = async (development_server_options = {}) => {\n const test_port_occupied = await check_if_port_occupied(1977);\n if (test_port_occupied) {\n await kill_port_process(1977);\n }\n\n // NOTE: Start test server using the same development_server function\n // but with different options to avoid recursion and environment conflicts\n setTimeout(async () => {\n try {\n await development_server({\n environment: 'test',\n port: 1977,\n watch: false, // No file watching for test server\n imports: development_server_options?.imports || [],\n _is_test_server: true, // Internal flag to prevent infinite recursion\n });\n } catch (error) {\n console.error('Error starting test server:', error);\n }\n }, 100); // Small delay to let main server start first\n};\n\nconst stop_test_server = () => {\n if (test_server_process) {\n test_server_process.kill();\n test_server_process = null;\n }\n test_server_ready = false;\n};\n\nconst reset_server_readiness = () => {\n main_server_ready = false;\n test_server_ready = false;\n};\n\nconst handle_run_tests = async (watch = false) => {\n const database_process_ids = get_database_process_ids();\n await run_tests({\n watch,\n __dirname,\n process_ids: [\n ...process_ids,\n ...database_process_ids,\n ],\n cleanup_process: process.cleanup_process,\n });\n};\n\nconst handle_signal_events = (process_ids = [], node_major_version = 0, __dirname = '') => {\n const exec_argv = [\"--no-warnings\"];\n\n if (node_major_version < 19) {\n exec_argv.push(\"--experimental-specifier-resolution=node\");\n }\n\n const cleanup_process = child_process.fork(\n path.resolve(`${__dirname}/cleanup.js`),\n [],\n {\n // NOTE: Run in detached mode so when parent process dies, the child still runs\n // and cleanup completes. Keep silent as we don't wan't/expect any messages.\n detached: true,\n silent: true,\n }\n );\n\n process.cleanup_process = cleanup_process;\n\n process.on(\"SIGINT\", async () => {\n const database_process_ids = get_database_process_ids();\n cleanup_process.send(JSON.stringify(({ process_ids: [...process_ids, ...database_process_ids] })));\n process.exit();\n });\n\n process.on(\"SIGTERM\", async () => {\n const database_process_ids = get_database_process_ids();\n cleanup_process.send(JSON.stringify(({ process_ids: [...process_ids, ...database_process_ids] })));\n process.exit();\n });\n};\n\nconst handle_signal_hmr_update = async (jobs = []) => {\n const has_settings_change = jobs?.find((job) => (job?.path?.match(constants.SETTINGS_FILE_NAME_REGEX))?.length > 0);\n const has_i18n_change = jobs?.find((job) => job?.path?.includes('i18n'));\n const has_index_html_change = jobs?.find((job) => job?.path?.includes('index.html'));\n const has_index_css_change = jobs?.find((job) => {\n return job?.path?.includes('index.css') || job?.path?.includes('css/');\n });\n const has_index_client_change = jobs?.find((job) => job?.path?.includes('index.client.js'));\n\n process.hmr_server_process.send(JSON.stringify({\n type: 'FILE_CHANGE',\n settings: has_settings_change ? await load_settings(process.env.NODE_ENV) : null,\n i18n_change: !!has_i18n_change,\n index_html_change: !!has_index_html_change,\n index_css_change: !!has_index_css_change,\n index_client_change: !!has_index_client_change,\n }));\n};\n\nconst handle_hmr_server_process_messages = (node_major_version = 0, watch = false, old_settings = {}, imports = [], run_integrated_tests = false) => {\n process.hmr_server_process.on(\"message\", async (message) => {\n const process_messages = [\n \"HAS_HMR_CONNECTIONS\",\n \"HAS_NO_HMR_CONNECTIONS\",\n \"HMR_UPDATE_COMPLETE\",\n ];\n\n if (!process_messages.includes(message?.type)) {\n process.loader.print(message);\n }\n\n if (message?.type === \"HAS_HMR_CONNECTIONS\") {\n process.hmr_server_process.has_connections = true;\n }\n\n if (message?.type === \"HAS_NO_HMR_CONNECTIONS\") {\n process.hmr_server_process.has_connections = false;\n }\n\n if (message?.type === \"HMR_UPDATE_COMPLETE\") {\n if (process.app_server_process && !process.app_server_restarting) {\n process.app_server_restarting = true;\n handle_restart_app_server(node_major_version, watch, old_settings, imports, run_integrated_tests);\n }\n }\n });\n};\n\nconst handle_hmr_server_process_stdio = () => {\n process.hmr_server_process.on(\"error\", (error) => {\n cli_log(error.toString(), {\n level: \"danger\",\n docs: \"https://github.com/cheatcode/joystick\",\n });\n });\n\n process.hmr_server_process.stdout.on(\"data\", (data) => {\n console.log(data.toString());\n });\n\n process.hmr_server_process.stderr.on(\"data\", (data) => {\n cli_log(data.toString(), {\n level: \"danger\",\n docs: \"https://github.com/cheatcode/joystick\",\n });\n });\n};\n\nconst handle_start_hmr_server = (node_major_version = 0, __dirname = '', watch = false, old_settings = {}, imports = [], run_integrated_tests = false) => {\n\tprocess.hmr_server_process = start_hmr_server(node_major_version, __dirname);\n process_ids.push(process.hmr_server_process?.pid);\n handle_hmr_server_process_stdio();\n handle_hmr_server_process_messages(node_major_version, watch, old_settings, imports, run_integrated_tests);\n};\n\nconst check_if_database_changes = async (old_settings = {}) => {\n const new_settings = await load_settings(process.env.NODE_ENV);\n const new_databse_settings = new_settings?.config?.databases ? JSON.stringify(new_settings?.config?.databases) : '';\n const old_database_settings = old_settings?.config?.databases ? JSON.stringify(old_settings?.config?.databases) : '';\n return new_databse_settings !== old_database_settings;\n};\n\nconst handle_restart_app_server = async (node_major_version = 0, watch = false, old_settings = null, imports = [], run_integrated_tests = false) => {\n debounce(async () => {\n const has_database_changes = await check_if_database_changes(old_settings);\n\n if (has_database_changes) {\n const database_process_ids = get_database_process_ids();\n\n cli_log(`Database configuration has changed in settings.${process.env.NODE_ENV}.json. Please restart your app to add, change, or remove databases.`, {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick/structure\",\n });\n\n kill_process_ids([\n process.hmr_server_process?.pid,\n process.app_server_process?.pid,\n ...database_process_ids,\n ]);\n\n process.exit(0);\n } else {\n // NOTE: Reset server readiness states when restarting\n if (run_integrated_tests) {\n reset_server_readiness();\n stop_test_server();\n }\n\n kill_process_ids([\n ...(process.app_server_process.external_process_ids || []),\n ]);\n\n await kill_port_process(process.env.PORT);\n handle_start_app_server(node_major_version, watch, imports, run_integrated_tests);\n\n // NOTE: Restart test server if tests are enabled\n if (run_integrated_tests) {\n await start_test_server({\n imports: imports || [],\n });\n }\n }\n }, 300);\n};\n\nconst handle_app_server_process_stdio = (watch = false, run_integrated_tests = false, is_test_server = false) => {\n // NOTE: Default this in case we never get any external process IDs.\n process.app_server_process.external_process_ids = [];\n\n process.app_server_process.on('message', (message_from_child) => {\n if (message_from_child?.external_process_id) {\n process.app_server_process.external_process_ids = [\n ...(process.app_server_process.external_process_ids || []),\n message_from_child?.external_process_id,\n ];\n }\n });\n\n process.app_server_process.on('error', (error) => {\n if (!is_test_server) {\n cli_log(error.toString(), {\n level: \"danger\",\n docs: \"https://github.com/cheatcode/joystick\",\n });\n }\n });\n\n process.app_server_process.stdout.on(\"data\", async (data) => {\n \tconst stdout = data.toString();\n const is_startup_notification = stdout.includes(\"App running at:\");\n\n // NOTE: Suppress all test server output\n if (is_test_server) {\n return;\n }\n\n // NOTE: Main server output handling\n \tif (stdout && is_startup_notification && process.env.NODE_ENV !== 'test') {\n \t\tprocess.loader.print(stdout);\n \t}\n\n if (stdout && !is_startup_notification && !stdout.includes(\"BUILD_ERROR\")) {\n console.log(stdout);\n }\n\n // NOTE: For test server, don't run the standalone test runner - just mark as ready\n if (stdout && is_startup_notification && process.env.NODE_ENV === 'test') {\n // NOTE: Test server is ready, but don't run tests here - they'll be run by the integrated runner\n }\n\n // NOTE: Mark main server as ready when --tests flag is used\n if (stdout && is_startup_notification && run_integrated_tests && process.env.NODE_ENV !== 'test') {\n main_server_ready = true;\n check_and_run_tests();\n }\n\n // NOTE: Mark test server as ready when it starts up\n if (stdout && is_startup_notification && process.env.NODE_ENV === 'test') {\n test_server_ready = true;\n check_and_run_tests();\n }\n });\n\n process.app_server_process.stderr.on(\"data\", (data) => {\n if (!is_test_server) {\n cli_log(data.toString(), {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick\",\n });\n }\n });\n};\n\nconst handle_start_app_server = (node_major_version = 0, watch = false, imports = [], run_integrated_tests = false, is_test_server = false) => {\n\tprocess.app_server_process = start_app_server(node_major_version, watch, imports);\n process_ids.push(process.app_server_process?.pid);\n handle_app_server_process_stdio(watch, run_integrated_tests, is_test_server);\n process.app_server_restarting = false;\n};\n\nconst install_missing_databases = async (settings = {}) => {\n const required_databases = settings?.config?.databases?.map((database = {}) => {\n return database?.provider;\n });\n\n for (let i = 0; i < required_databases?.length; i += 1) {\n const provider_name = required_databases[i];\n await download_database_binary(provider_name);\n }\n};\n\nconst set_process_variables = (development_server_options = {}, port = 2600) => {\n process.title = development_server_options?.environment === 'test' ? \"joystick_test\" : 'joystick';\n process.project_folder = path.basename(process.cwd());\n process.loader = new Loader();\n\n if (development_server_options?.environment === 'test') {\n console.log(''); // NOTE: Silly, but gives us better styling.\n process.loader.print(\"Initializing test environment...\\n\");\n }\n\n process.env.LOGS_PATH = development_server_options?.logs || null;\n process.env.NODE_ENV = development_server_options?.environment || \"development\";\n process.env.PORT = port;\n process.env.IS_DEBUG_MODE = development_server_options?.debug;\n};\n\nconst warn_app_port_occupied = (port = 2600) => {\n cli_log(`Port ${port} is already occupied. To start Joystick on this port, clear it and try again.`, {\n level: 'danger',\n });\n\n process.exit(0);\n};\n\nconst get_port = (port = 2600) => {\n\treturn parseInt(port || 2600, 10);\n};\n\nconst clean_up_existing_build = async () => {\n\tconst build_path = get_platform_safe_path(`${process.cwd()}/.joystick/build`);\n\n\tif (await path_exists(build_path)) {\n\t\tawait exec(`${process.platform === 'win32' ? 'rmdir /s /q' : 'rm -rf'} ${build_path}`);\n\t}\n};\n\nconst check_for_required_files = async () => {\n const missing_files = [];\n\n for (let i = 0; i < required_files?.length; i += 1) {\n const required_file = required_files[i];\n const exists = await path_exists(`${process.cwd()}/${required_file.path}`);\n const stats = exists && await stat(`${process.cwd()}/${required_file.path}`);\n\n if (required_file && required_file.type === \"file\" && (!exists || (exists && !stats.isFile()))) {\n missing_files.push({ type: 'file', path: required_file.path });\n }\n\n if (required_file && required_file.type === \"directory\" && (!exists || (exists && !stats.isDirectory()))) {\n missing_files.push({ type: 'directory', path: required_file.path });\n }\n }\n\n if (missing_files?.length > 0) {\n const files = missing_files?.filter((path) => path.type === 'file');\n const directories = missing_files?.filter((path) => path.type === 'directory');\n\n let error = `The following paths are missing and required in a Joystick project:\\n\\n`;\n\n if (files?.length > 0) {\n error += ` ${chalk.yellow('>')} Required Files:\\n\\n`;\n\n for (let i = 0; i < files?.length; i += 1) {\n const file = files[i];\n const is_last_file = i +1 === files?.length;\n error += ` ${chalk.red(`/${file.path}\\n${is_last_file && directories?.length > 0 ? '\\n' : ''}`)}`;\n }\n }\n\n if (directories?.length > 0) {\n error += ` ${chalk.yellow('>')} Required Directories:\\n\\n`;\n\n for (let i = 0; i < directories?.length; i += 1) {\n const file = directories[i];\n error += ` ${chalk.red(`/${file.path}\\n`)}`;\n }\n }\n\n cli_log(error, {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick/structure\",\n });\n\n process.exit(0);\n }\n};\n\nconst warn_invalid_joystick_environment = async () => {\n const has_joystick_folder = await path_exists(`${process.cwd()}/.joystick`);\n const has_tests_folder = await path_exists(`${process.cwd()}/tests`);\n\n if (process.env.NODE_ENV === 'test' && (!has_joystick_folder || !has_tests_folder)) {\n cli_log(\n \"joystick test must be run in a directory with a .joystick folder and tests folder.\",\n {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick/cli/test\",\n }\n );\n\n process.exit(0);\n }\n\n if (process.env.NODE_ENV !== 'test' && !has_joystick_folder) {\n cli_log(\n \"joystick start must be run in a directory with a .joystick folder.\",\n {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick/cli/start\",\n }\n );\n\n process.exit(0);\n }\n};\n\nconst development_server = async (development_server_options = {}) => {\n await warn_invalid_joystick_environment();\n await check_for_required_files();\n\n\tawait clean_up_existing_build();\n\n\tconst port = get_port(development_server_options?.port);\n\tconst app_port_occupied = await check_if_port_occupied(port);\n const hmr_port_occupied = await check_if_port_occupied(port + 1);\n\n if (app_port_occupied) {\n \twarn_app_port_occupied(port);\n }\n\n if (hmr_port_occupied) {\n \tkill_port_process(port);\n }\n\n set_process_variables(development_server_options, port);\n\n const settings = await load_settings(process.env.NODE_ENV);\n\n await install_missing_databases(settings);\n\n await start_databases({\n environment: process.env.NODE_ENV,\n port,\n settings\n });\n\n // NOTE: Start test server if tests flag is enabled and this is not already a test server\n if (development_server_options?.tests && development_server_options?.environment !== 'test' && !development_server_options?._is_test_server) {\n await start_test_server({\n imports: development_server_options?.imports || [],\n });\n }\n\n\n // NOTE: Only set up file watching for non-test servers\n if (!development_server_options?._is_test_server) {\n watch_for_changes({\n hot_module_reload: (jobs = []) => handle_signal_hmr_update(jobs),\n restart_app_server: () => handle_restart_app_server(\n node_major_version,\n development_server_options?.watch,\n settings,\n development_server_options?.imports,\n development_server_options?.tests,\n ),\n start_app_server: () => handle_start_app_server(\n node_major_version,\n development_server_options?.watch,\n development_server_options?.imports,\n development_server_options?.tests,\n development_server_options?._is_test_server,\n ),\n start_hmr_server: development_server_options?.environment !== 'test' ? () => handle_start_hmr_server(\n node_major_version,\n __dirname,\n development_server_options?.watch,\n settings,\n development_server_options?.imports,\n development_server_options?.tests,\n ) : null,\n run_tests: development_server_options?.tests ? async () => {\n // NOTE: Add delay to avoid jarring UX when test files change\n setTimeout(async () => {\n try {\n await run_tests_integrated({\n __dirname,\n });\n } catch (error) {\n console.error('Error running tests after file change:', error);\n }\n }, 1000);\n } : null,\n }, {\n excluded_paths: settings?.config?.build?.excluded_paths,\n custom_copy_paths: settings?.config?.build?.copy_paths?.map((path) => {\n return { path };\n }) || [],\n });\n } else {\n // NOTE: For test server, just start the app server without file watching\n handle_start_app_server(\n node_major_version,\n false, // No file watching for test server\n development_server_options?.imports || [],\n false, // No integrated tests for test server\n true, // This is a test server\n );\n }\n\n handle_signal_events(process_ids, node_major_version, __dirname);\n};\n\nexport default development_server;\n"],
5
- "mappings": "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",
6
- "names": ["chalk", "child_process", "fs", "path", "dirname", "fileURLToPath", "util", "check_if_port_occupied", "cli_log", "get_database_process_ids", "get_platform_safe_path", "kill_port_process", "load_settings", "Loader", "path_exists", "required_files", "start_app_server", "start_databases", "start_hmr_server", "watch_for_changes", "constants", "kill_process_ids", "run_tests", "run_tests_integrated", "debounce", "download_database_binary", "stat", "exec", "node_major_version", "__filename", "__dirname", "process_ids", "test_server_process", "main_server_ready", "test_server_ready", "check_and_run_tests", "error", "start_test_server", "development_server_options", "development_server", "stop_test_server", "reset_server_readiness", "handle_run_tests", "watch", "database_process_ids", "handle_signal_events", "exec_argv", "cleanup_process", "handle_signal_hmr_update", "jobs", "has_settings_change", "job", "has_i18n_change", "has_index_html_change", "has_index_css_change", "has_index_client_change", "handle_hmr_server_process_messages", "old_settings", "imports", "run_integrated_tests", "message", "handle_restart_app_server", "handle_hmr_server_process_stdio", "data", "handle_start_hmr_server", "check_if_database_changes", "new_settings", "new_databse_settings", "old_database_settings", "handle_start_app_server", "handle_app_server_process_stdio", "is_test_server", "message_from_child", "stdout", "is_startup_notification", "install_missing_databases", "settings", "required_databases", "database", "i", "provider_name", "set_process_variables", "port", "warn_app_port_occupied", "get_port", "clean_up_existing_build", "build_path", "check_for_required_files", "missing_files", "required_file", "exists", "stats", "files", "directories", "file", "is_last_file", "warn_invalid_joystick_environment", "has_joystick_folder", "has_tests_folder", "app_port_occupied", "hmr_port_occupied", "index_default"]
4
+ "sourcesContent": ["import chalk from 'chalk';\nimport child_process from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path, { dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport util from 'util';\nimport check_if_port_occupied from './check_if_port_occupied.js';\nimport cli_log from '../cli_log.js';\nimport get_database_process_ids from './get_database_process_ids.js';\n import get_platform_safe_path from '../get_platform_safe_path.js';\nimport kill_port_process from '../kill_port_process.js';\nimport load_settings from '../load_settings.js';\nimport Loader from '../loader.js';\nimport path_exists from '../path_exists.js';\nimport required_files from '../required_files.js';\nimport start_app_server from './start_app_server.js';\nimport start_databases from './start_databases.js';\nimport start_hmr_server from './start_hmr_server.js';\nimport watch_for_changes from './watch_for_changes/index.js';\nimport constants from '../constants.js';\nimport kill_process_ids from './kill_process_ids.js';\nimport run_tests, { run_tests_integrated } from './run_tests.js';\nimport debounce from '../debounce.js';\nimport download_database_binary from './databases/download_database_binary.js';\n\nconst { stat } = fs.promises;\nconst exec = util.promisify(child_process.exec);\n\nconst node_major_version = parseInt(\n process?.version?.split(\".\")[0]?.replace(\"v\", \"\"),\n 10\n);\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst process_ids = [];\n\nconst handle_run_tests = async (watch = false) => {\n const database_process_ids = get_database_process_ids();\n await run_tests({\n watch,\n __dirname,\n process_ids: [\n ...process_ids,\n ...database_process_ids,\n ],\n cleanup_process: process.cleanup_process,\n });\n};\n\nconst handle_signal_events = (process_ids = [], node_major_version = 0, __dirname = '') => {\n const exec_argv = [\"--no-warnings\"];\n\n if (node_major_version < 19) {\n exec_argv.push(\"--experimental-specifier-resolution=node\");\n }\n\n const cleanup_process = child_process.fork(\n path.resolve(`${__dirname}/cleanup.js`),\n [],\n {\n // NOTE: Run in detached mode so when parent process dies, the child still runs\n // and cleanup completes. Keep silent as we don't wan't/expect any messages.\n detached: true,\n silent: true,\n }\n );\n\n process.cleanup_process = cleanup_process;\n\n process.on(\"SIGINT\", async () => {\n const database_process_ids = get_database_process_ids();\n cleanup_process.send(JSON.stringify(({ process_ids: [...process_ids, ...database_process_ids] })));\n process.exit();\n });\n\n process.on(\"SIGTERM\", async () => {\n const database_process_ids = get_database_process_ids();\n cleanup_process.send(JSON.stringify(({ process_ids: [...process_ids, ...database_process_ids] })));\n process.exit();\n });\n};\n\nconst handle_signal_hmr_update = async (jobs = []) => {\n const has_settings_change = jobs?.find((job) => (job?.path?.match(constants.SETTINGS_FILE_NAME_REGEX))?.length > 0);\n const has_i18n_change = jobs?.find((job) => job?.path?.includes('i18n'));\n const has_index_html_change = jobs?.find((job) => job?.path?.includes('index.html'));\n const has_index_css_change = jobs?.find((job) => {\n return job?.path?.includes('index.css') || job?.path?.includes('css/');\n });\n const has_index_client_change = jobs?.find((job) => job?.path?.includes('index.client.js'));\n\n process.hmr_server_process.send(JSON.stringify({\n type: 'FILE_CHANGE',\n settings: has_settings_change ? await load_settings(process.env.NODE_ENV) : null,\n i18n_change: !!has_i18n_change,\n index_html_change: !!has_index_html_change,\n index_css_change: !!has_index_css_change,\n index_client_change: !!has_index_client_change,\n }));\n};\n\nconst handle_hmr_server_process_messages = (node_major_version = 0, watch = false, old_settings = {}, imports = [], run_integrated_tests = false) => {\n process.hmr_server_process.on(\"message\", async (message) => {\n const process_messages = [\n \"HAS_HMR_CONNECTIONS\",\n \"HAS_NO_HMR_CONNECTIONS\",\n \"HMR_UPDATE_COMPLETE\",\n ];\n\n if (!process_messages.includes(message?.type)) {\n process.loader.print(message);\n }\n\n if (message?.type === \"HAS_HMR_CONNECTIONS\") {\n process.hmr_server_process.has_connections = true;\n }\n\n if (message?.type === \"HAS_NO_HMR_CONNECTIONS\") {\n process.hmr_server_process.has_connections = false;\n }\n\n if (message?.type === \"HMR_UPDATE_COMPLETE\") {\n if (process.app_server_process && !process.app_server_restarting) {\n process.app_server_restarting = true;\n handle_restart_app_server(node_major_version, watch, old_settings, imports, run_integrated_tests);\n }\n }\n });\n};\n\nconst handle_hmr_server_process_stdio = () => {\n process.hmr_server_process.on(\"error\", (error) => {\n cli_log(error.toString(), {\n level: \"danger\",\n docs: \"https://github.com/cheatcode/joystick\",\n });\n });\n\n process.hmr_server_process.stdout.on(\"data\", (data) => {\n console.log(data.toString());\n });\n\n process.hmr_server_process.stderr.on(\"data\", (data) => {\n cli_log(data.toString(), {\n level: \"danger\",\n docs: \"https://github.com/cheatcode/joystick\",\n });\n });\n};\n\nconst handle_start_hmr_server = (node_major_version = 0, __dirname = '', watch = false, old_settings = {}, imports = [], run_integrated_tests = false) => {\n\tprocess.hmr_server_process = start_hmr_server(node_major_version, __dirname);\n process_ids.push(process.hmr_server_process?.pid);\n handle_hmr_server_process_stdio();\n handle_hmr_server_process_messages(node_major_version, watch, old_settings, imports, run_integrated_tests);\n};\n\nconst check_if_database_changes = async (old_settings = {}) => {\n const new_settings = await load_settings(process.env.NODE_ENV);\n const new_databse_settings = new_settings?.config?.databases ? JSON.stringify(new_settings?.config?.databases) : '';\n const old_database_settings = old_settings?.config?.databases ? JSON.stringify(old_settings?.config?.databases) : '';\n return new_databse_settings !== old_database_settings;\n};\n\nconst handle_restart_app_server = async (node_major_version = 0, watch = false, old_settings = null, imports = [], run_integrated_tests = false) => {\n debounce(async () => {\n const has_database_changes = await check_if_database_changes(old_settings);\n\n if (has_database_changes) {\n const database_process_ids = get_database_process_ids();\n\n cli_log(`Database configuration has changed in settings.${process.env.NODE_ENV}.json. Please restart your app to add, change, or remove databases.`, {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick/structure\",\n });\n\n kill_process_ids([\n process.hmr_server_process?.pid,\n process.app_server_process?.pid,\n ...database_process_ids,\n ]);\n\n process.exit(0);\n } else {\n kill_process_ids([\n ...(process.app_server_process.external_process_ids || []),\n ]);\n\n await kill_port_process(process.env.PORT);\n handle_start_app_server(node_major_version, watch, imports, run_integrated_tests);\n }\n }, 300);\n};\n\nconst handle_app_server_process_stdio = (watch = false, run_integrated_tests = false, is_test_server = false) => {\n // NOTE: Default this in case we never get any external process IDs.\n process.app_server_process.external_process_ids = [];\n\n process.app_server_process.on('message', (message_from_child) => {\n if (message_from_child?.external_process_id) {\n process.app_server_process.external_process_ids = [\n ...(process.app_server_process.external_process_ids || []),\n message_from_child?.external_process_id,\n ];\n }\n });\n\n process.app_server_process.on('error', (error) => {\n if (!is_test_server) {\n cli_log(error.toString(), {\n level: \"danger\",\n docs: \"https://github.com/cheatcode/joystick\",\n });\n }\n });\n\n process.app_server_process.stdout.on(\"data\", async (data) => {\n \tconst stdout = data.toString();\n const is_startup_notification = stdout.includes(\"App running at:\");\n\n // NOTE: Suppress all test server output\n if (is_test_server) {\n return;\n }\n\n // NOTE: Main server output handling\n \tif (stdout && is_startup_notification && process.env.NODE_ENV !== 'test') {\n \t\tprocess.loader.print(stdout);\n \t}\n\n if (stdout && !is_startup_notification && !stdout.includes(\"BUILD_ERROR\")) {\n console.log(stdout);\n }\n\n // NOTE: Run tests here so we can guarantee app server is running. Do a slight delay\n // to ensure that test routes are registered.\n if (stdout && is_startup_notification && process.env.NODE_ENV === 'test') {\n handle_run_tests(watch);\n }\n\n // NOTE: Run integrated tests when --tests flag is used and server has started\n if (stdout && is_startup_notification && run_integrated_tests && process.env.NODE_ENV !== 'test') {\n // NOTE: Add delay to avoid jarring UX and ensure server is fully ready\n setTimeout(async () => {\n try {\n await run_tests_integrated({\n __dirname,\n });\n } catch (error) {\n console.error('Error running integrated tests:', error);\n }\n }, 2000);\n }\n });\n\n process.app_server_process.stderr.on(\"data\", (data) => {\n if (!is_test_server) {\n cli_log(data.toString(), {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick\",\n });\n }\n });\n};\n\nconst handle_start_app_server = (node_major_version = 0, watch = false, imports = [], run_integrated_tests = false, is_test_server = false) => {\n\tprocess.app_server_process = start_app_server(node_major_version, watch, imports);\n process_ids.push(process.app_server_process?.pid);\n handle_app_server_process_stdio(watch, run_integrated_tests, is_test_server);\n process.app_server_restarting = false;\n};\n\nconst install_missing_databases = async (settings = {}) => {\n const required_databases = settings?.config?.databases?.map((database = {}) => {\n return database?.provider;\n });\n\n for (let i = 0; i < required_databases?.length; i += 1) {\n const provider_name = required_databases[i];\n await download_database_binary(provider_name);\n }\n};\n\nconst set_process_variables = (development_server_options = {}, port = 2600) => {\n process.title = development_server_options?.environment === 'test' ? \"joystick_test\" : 'joystick';\n process.project_folder = path.basename(process.cwd());\n process.loader = new Loader();\n\n if (development_server_options?.environment === 'test') {\n console.log(''); // NOTE: Silly, but gives us better styling.\n process.loader.print(\"Initializing test environment...\\n\");\n }\n\n process.env.LOGS_PATH = development_server_options?.logs || null;\n process.env.NODE_ENV = development_server_options?.environment || \"development\";\n process.env.PORT = port;\n process.env.IS_DEBUG_MODE = development_server_options?.debug;\n};\n\nconst warn_app_port_occupied = (port = 2600) => {\n cli_log(`Port ${port} is already occupied. To start Joystick on this port, clear it and try again.`, {\n level: 'danger',\n });\n\n process.exit(0);\n};\n\nconst get_port = (port = 2600) => {\n\treturn parseInt(port || 2600, 10);\n};\n\nconst clean_up_existing_build = async () => {\n\tconst build_path = get_platform_safe_path(`${process.cwd()}/.joystick/build`);\n\n\tif (await path_exists(build_path)) {\n\t\tawait exec(`${process.platform === 'win32' ? 'rmdir /s /q' : 'rm -rf'} ${build_path}`);\n\t}\n};\n\nconst check_for_required_files = async () => {\n const missing_files = [];\n\n for (let i = 0; i < required_files?.length; i += 1) {\n const required_file = required_files[i];\n const exists = await path_exists(`${process.cwd()}/${required_file.path}`);\n const stats = exists && await stat(`${process.cwd()}/${required_file.path}`);\n\n if (required_file && required_file.type === \"file\" && (!exists || (exists && !stats.isFile()))) {\n missing_files.push({ type: 'file', path: required_file.path });\n }\n\n if (required_file && required_file.type === \"directory\" && (!exists || (exists && !stats.isDirectory()))) {\n missing_files.push({ type: 'directory', path: required_file.path });\n }\n }\n\n if (missing_files?.length > 0) {\n const files = missing_files?.filter((path) => path.type === 'file');\n const directories = missing_files?.filter((path) => path.type === 'directory');\n\n let error = `The following paths are missing and required in a Joystick project:\\n\\n`;\n\n if (files?.length > 0) {\n error += ` ${chalk.yellow('>')} Required Files:\\n\\n`;\n\n for (let i = 0; i < files?.length; i += 1) {\n const file = files[i];\n const is_last_file = i +1 === files?.length;\n error += ` ${chalk.red(`/${file.path}\\n${is_last_file && directories?.length > 0 ? '\\n' : ''}`)}`;\n }\n }\n\n if (directories?.length > 0) {\n error += ` ${chalk.yellow('>')} Required Directories:\\n\\n`;\n\n for (let i = 0; i < directories?.length; i += 1) {\n const file = directories[i];\n error += ` ${chalk.red(`/${file.path}\\n`)}`;\n }\n }\n\n cli_log(error, {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick/structure\",\n });\n\n process.exit(0);\n }\n};\n\nconst warn_invalid_joystick_environment = async () => {\n const has_joystick_folder = await path_exists(`${process.cwd()}/.joystick`);\n const has_tests_folder = await path_exists(`${process.cwd()}/tests`);\n\n if (process.env.NODE_ENV === 'test' && (!has_joystick_folder || !has_tests_folder)) {\n cli_log(\n \"joystick test must be run in a directory with a .joystick folder and tests folder.\",\n {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick/cli/test\",\n }\n );\n\n process.exit(0);\n }\n\n if (process.env.NODE_ENV !== 'test' && !has_joystick_folder) {\n cli_log(\n \"joystick start must be run in a directory with a .joystick folder.\",\n {\n level: \"danger\",\n docs: \"https://cheatcode.co/docs/joystick/cli/start\",\n }\n );\n\n process.exit(0);\n }\n};\n\nconst development_server = async (development_server_options = {}) => {\n await warn_invalid_joystick_environment();\n await check_for_required_files();\n\n\tawait clean_up_existing_build();\n\n\tconst port = get_port(development_server_options?.port);\n\tconst app_port_occupied = await check_if_port_occupied(port);\n const hmr_port_occupied = await check_if_port_occupied(port + 1);\n\n if (app_port_occupied) {\n \twarn_app_port_occupied(port);\n }\n\n if (hmr_port_occupied) {\n \tkill_port_process(port);\n }\n\n set_process_variables(development_server_options, port);\n\n const settings = await load_settings(process.env.NODE_ENV);\n\n await install_missing_databases(settings);\n\n await start_databases({\n environment: process.env.NODE_ENV,\n port,\n settings\n });\n\n // NOTE: If tests flag is enabled, start a separate test server on port 1977\n if (development_server_options?.tests && development_server_options?.environment !== 'test') {\n const test_port_occupied = await check_if_port_occupied(1977);\n if (test_port_occupied) {\n await kill_port_process(1977);\n }\n\n // NOTE: Start test server in parallel using the same development_server function\n // but with different options to avoid recursion and environment conflicts\n setTimeout(async () => {\n try {\n await development_server({\n environment: 'test',\n port: 1977,\n watch: false, // No file watching for test server\n imports: development_server_options?.imports || [],\n _is_test_server: true, // Internal flag to prevent infinite recursion\n });\n } catch (error) {\n console.error('Error starting test server:', error);\n }\n }, 100); // Small delay to let main server start first\n }\n\n // NOTE: Only set up file watching for non-test servers\n if (!development_server_options?._is_test_server) {\n watch_for_changes({\n hot_module_reload: (jobs = []) => handle_signal_hmr_update(jobs),\n restart_app_server: () => handle_restart_app_server(\n node_major_version,\n development_server_options?.watch,\n settings,\n development_server_options?.imports,\n development_server_options?.tests,\n ),\n start_app_server: () => handle_start_app_server(\n node_major_version,\n development_server_options?.watch,\n development_server_options?.imports,\n development_server_options?.tests,\n development_server_options?._is_test_server,\n ),\n start_hmr_server: development_server_options?.environment !== 'test' ? () => handle_start_hmr_server(\n node_major_version,\n __dirname,\n development_server_options?.watch,\n settings,\n development_server_options?.imports,\n development_server_options?.tests,\n ) : null,\n run_tests: development_server_options?.tests ? async () => {\n // NOTE: Add delay to avoid jarring UX when test files change\n setTimeout(async () => {\n try {\n await run_tests_integrated({\n __dirname,\n });\n } catch (error) {\n console.error('Error running tests after file change:', error);\n }\n }, 1000);\n } : null,\n }, {\n excluded_paths: settings?.config?.build?.excluded_paths,\n custom_copy_paths: settings?.config?.build?.copy_paths?.map((path) => {\n return { path };\n }) || [],\n });\n } else {\n // NOTE: For test server, just start the app server without file watching\n handle_start_app_server(\n node_major_version,\n false, // No file watching for test server\n development_server_options?.imports || [],\n false, // No integrated tests for test server\n true, // This is a test server\n );\n }\n\n handle_signal_events(process_ids, node_major_version, __dirname);\n};\n\nexport default development_server;\n"],
5
+ "mappings": "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",
6
+ "names": ["chalk", "child_process", "fs", "path", "dirname", "fileURLToPath", "util", "check_if_port_occupied", "cli_log", "get_database_process_ids", "get_platform_safe_path", "kill_port_process", "load_settings", "Loader", "path_exists", "required_files", "start_app_server", "start_databases", "start_hmr_server", "watch_for_changes", "constants", "kill_process_ids", "run_tests", "run_tests_integrated", "debounce", "download_database_binary", "stat", "exec", "node_major_version", "__filename", "__dirname", "process_ids", "handle_run_tests", "watch", "database_process_ids", "handle_signal_events", "exec_argv", "cleanup_process", "handle_signal_hmr_update", "jobs", "has_settings_change", "job", "has_i18n_change", "has_index_html_change", "has_index_css_change", "has_index_client_change", "handle_hmr_server_process_messages", "old_settings", "imports", "run_integrated_tests", "message", "handle_restart_app_server", "handle_hmr_server_process_stdio", "error", "data", "handle_start_hmr_server", "check_if_database_changes", "new_settings", "new_databse_settings", "old_database_settings", "handle_start_app_server", "handle_app_server_process_stdio", "is_test_server", "message_from_child", "stdout", "is_startup_notification", "install_missing_databases", "settings", "required_databases", "database", "i", "provider_name", "set_process_variables", "development_server_options", "port", "warn_app_port_occupied", "get_port", "clean_up_existing_build", "build_path", "check_for_required_files", "missing_files", "required_file", "exists", "stats", "files", "directories", "file", "is_last_file", "warn_invalid_joystick_environment", "has_joystick_folder", "has_tests_folder", "development_server", "app_port_occupied", "hmr_port_occupied", "index_default"]
7
7
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@joystick.js/cli-canary",
3
3
  "type": "module",
4
- "version": "0.0.0-canary.2137",
5
- "canary_version": "0.0.0-canary.2136",
4
+ "version": "0.0.0-canary.2139",
5
+ "canary_version": "0.0.0-canary.2138",
6
6
  "description": "The CLI for Joystick.",
7
7
  "main": "dist/index.js",
8
8
  "bin": {
@@ -37,63 +37,6 @@ const __dirname = dirname(__filename);
37
37
 
38
38
  const process_ids = [];
39
39
 
40
- // NOTE: Global test server process tracking and server readiness state
41
- let test_server_process = null;
42
- let main_server_ready = false;
43
- let test_server_ready = false;
44
-
45
- const check_and_run_tests = async () => {
46
- if (main_server_ready && test_server_ready) {
47
- // NOTE: Add 2s delay to ensure both servers are fully ready
48
- setTimeout(async () => {
49
- console.log('Running tests...');
50
- try {
51
- await run_tests_integrated({
52
- __dirname,
53
- });
54
- } catch (error) {
55
- console.error('Error running integrated tests:', error);
56
- }
57
- }, 2000);
58
- }
59
- };
60
-
61
- const start_test_server = async (development_server_options = {}) => {
62
- const test_port_occupied = await check_if_port_occupied(1977);
63
- if (test_port_occupied) {
64
- await kill_port_process(1977);
65
- }
66
-
67
- // NOTE: Start test server using the same development_server function
68
- // but with different options to avoid recursion and environment conflicts
69
- setTimeout(async () => {
70
- try {
71
- await development_server({
72
- environment: 'test',
73
- port: 1977,
74
- watch: false, // No file watching for test server
75
- imports: development_server_options?.imports || [],
76
- _is_test_server: true, // Internal flag to prevent infinite recursion
77
- });
78
- } catch (error) {
79
- console.error('Error starting test server:', error);
80
- }
81
- }, 100); // Small delay to let main server start first
82
- };
83
-
84
- const stop_test_server = () => {
85
- if (test_server_process) {
86
- test_server_process.kill();
87
- test_server_process = null;
88
- }
89
- test_server_ready = false;
90
- };
91
-
92
- const reset_server_readiness = () => {
93
- main_server_ready = false;
94
- test_server_ready = false;
95
- };
96
-
97
40
  const handle_run_tests = async (watch = false) => {
98
41
  const database_process_ids = get_database_process_ids();
99
42
  await run_tests({
@@ -242,25 +185,12 @@ const handle_restart_app_server = async (node_major_version = 0, watch = false,
242
185
 
243
186
  process.exit(0);
244
187
  } else {
245
- // NOTE: Reset server readiness states when restarting
246
- if (run_integrated_tests) {
247
- reset_server_readiness();
248
- stop_test_server();
249
- }
250
-
251
188
  kill_process_ids([
252
189
  ...(process.app_server_process.external_process_ids || []),
253
190
  ]);
254
191
 
255
192
  await kill_port_process(process.env.PORT);
256
193
  handle_start_app_server(node_major_version, watch, imports, run_integrated_tests);
257
-
258
- // NOTE: Restart test server if tests are enabled
259
- if (run_integrated_tests) {
260
- await start_test_server({
261
- imports: imports || [],
262
- });
263
- }
264
194
  }
265
195
  }, 300);
266
196
  };
@@ -305,21 +235,24 @@ const handle_app_server_process_stdio = (watch = false, run_integrated_tests = f
305
235
  console.log(stdout);
306
236
  }
307
237
 
308
- // NOTE: For test server, don't run the standalone test runner - just mark as ready
238
+ // NOTE: Run tests here so we can guarantee app server is running. Do a slight delay
239
+ // to ensure that test routes are registered.
309
240
  if (stdout && is_startup_notification && process.env.NODE_ENV === 'test') {
310
- // NOTE: Test server is ready, but don't run tests here - they'll be run by the integrated runner
241
+ handle_run_tests(watch);
311
242
  }
312
243
 
313
- // NOTE: Mark main server as ready when --tests flag is used
244
+ // NOTE: Run integrated tests when --tests flag is used and server has started
314
245
  if (stdout && is_startup_notification && run_integrated_tests && process.env.NODE_ENV !== 'test') {
315
- main_server_ready = true;
316
- check_and_run_tests();
317
- }
318
-
319
- // NOTE: Mark test server as ready when it starts up
320
- if (stdout && is_startup_notification && process.env.NODE_ENV === 'test') {
321
- test_server_ready = true;
322
- check_and_run_tests();
246
+ // NOTE: Add delay to avoid jarring UX and ensure server is fully ready
247
+ setTimeout(async () => {
248
+ try {
249
+ await run_tests_integrated({
250
+ __dirname,
251
+ });
252
+ } catch (error) {
253
+ console.error('Error running integrated tests:', error);
254
+ }
255
+ }, 2000);
323
256
  }
324
257
  });
325
258
 
@@ -497,13 +430,29 @@ const development_server = async (development_server_options = {}) => {
497
430
  settings
498
431
  });
499
432
 
500
- // NOTE: Start test server if tests flag is enabled and this is not already a test server
501
- if (development_server_options?.tests && development_server_options?.environment !== 'test' && !development_server_options?._is_test_server) {
502
- await start_test_server({
503
- imports: development_server_options?.imports || [],
504
- });
505
- }
433
+ // NOTE: If tests flag is enabled, start a separate test server on port 1977
434
+ if (development_server_options?.tests && development_server_options?.environment !== 'test') {
435
+ const test_port_occupied = await check_if_port_occupied(1977);
436
+ if (test_port_occupied) {
437
+ await kill_port_process(1977);
438
+ }
506
439
 
440
+ // NOTE: Start test server in parallel using the same development_server function
441
+ // but with different options to avoid recursion and environment conflicts
442
+ setTimeout(async () => {
443
+ try {
444
+ await development_server({
445
+ environment: 'test',
446
+ port: 1977,
447
+ watch: false, // No file watching for test server
448
+ imports: development_server_options?.imports || [],
449
+ _is_test_server: true, // Internal flag to prevent infinite recursion
450
+ });
451
+ } catch (error) {
452
+ console.error('Error starting test server:', error);
453
+ }
454
+ }, 100); // Small delay to let main server start first
455
+ }
507
456
 
508
457
  // NOTE: Only set up file watching for non-test servers
509
458
  if (!development_server_options?._is_test_server) {