@stacksjs/actions 0.74.33 → 0.74.35
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/dist/deploy/index.js +1 -1
- package/dist/dev/dashboard.js +1 -1
- package/dist/queue/failed.js +1 -1
- package/dist/queue/list.js +1 -1
- package/package.json +40 -40
package/dist/deploy/index.js
CHANGED
|
@@ -241,7 +241,7 @@ SERVICEFILE`,"systemctl daemon-reload","systemctl enable stacks-smtp","systemctl
|
|
|
241
241
|
`)}
|
|
242
242
|
</Items>
|
|
243
243
|
</Paths>
|
|
244
|
-
</InvalidationBatch>`})}blogDeploySpinner.succeed(`Blog deployed to S3 (${blogBucketName})`)}}catch(blogDeployError){blogDeploySpinner.fail(`Blog deployment failed: ${blogDeployError.message}`);if(isVerbose)log.debug(`Blog deploy error: ${blogDeployError.stack}`)}}else if(isVerbose)log.debug("No blog build found at dist/blog, skipping blog deployment");const errorPageSpinner=spinner("Configuring 404 error page...");errorPageSpinner.start();try{const{S3Client,CloudFormationClient,AWSClient}=await import("@stacksjs/ts-cloud"),{existsSync:exists404,readFileSync:read404}=await import("node:fs"),s3=new S3Client(region),cf=new CloudFormationClient(region),awsClient=new AWSClient,stackName=`${projectName}-cloud`,outputs=await cf.getStackOutputs(stackName),
|
|
244
|
+
</InvalidationBatch>`})}blogDeploySpinner.succeed(`Blog deployed to S3 (${blogBucketName})`)}}catch(blogDeployError){blogDeploySpinner.fail(`Blog deployment failed: ${blogDeployError.message}`);if(isVerbose)log.debug(`Blog deploy error: ${blogDeployError.stack}`)}}else if(isVerbose)log.debug("No blog build found at dist/blog, skipping blog deployment");const errorPageSpinner=spinner("Configuring 404 error page...");errorPageSpinner.start();try{const{S3Client,CloudFormationClient,AWSClient}=await import("@stacksjs/ts-cloud"),{existsSync:exists404,readFileSync:read404}=await import("node:fs"),s3=new S3Client(region),cf=new CloudFormationClient(region),awsClient=new AWSClient,stackName=`${projectName}-cloud`,outputs=await cf.getStackOutputs(stackName),frontendBucket=outputs.FrontendBucketName,docsBucket=outputs.DocsBucketName,distributionId=outputs.publicCloudFrontDistributionId||outputs.CloudFrontDistributionId,docs404Path=p.projectPath("dist/docs/.bunpress/404.html");let html404Content;if(exists404(docs404Path)){html404Content=read404(docs404Path,"utf-8");if(isVerbose)log.debug(" Using BunPress-generated 404.html")}else{html404Content=`<!DOCTYPE html>
|
|
245
245
|
<html lang="en">
|
|
246
246
|
<head>
|
|
247
247
|
<meta charset="UTF-8">
|
package/dist/dev/dashboard.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import process from"node:process";import{randomUUID}from"node:crypto";import{existsSync,renameSync,unlinkSync,writeFileSync}from"node:fs";import{bold,cyan,dim,green}from"@stacksjs/cli";import{projectPath,publicPath,storagePath}from"@stacksjs/path";import{seedCsrfPageResponse,validateDevCsrfRequest}from"./csrf";import{shouldDelegateDashboardRequest}from"./dashboard-request-routing";import{resolveDashboardCraftExecutable}from"./dashboard-native";import{buildManifest,discoverModels,findAvailablePort,waitForServer}from"./dashboard-utils";import{runDashboardSupervisor}from"./dashboard-supervisor";if(process.env.STACKS_DASHBOARD_WORKER!=="1"){const exitCode=await runDashboardSupervisor(import.meta.path,process.argv.slice(2));process.exit(exitCode)}const verboseIdx=process.argv.indexOf("--verbose"),verbose=verboseIdx!==-1&&process.argv[verboseIdx+1]!=="false",startTime=Bun.nanoseconds(),
|
|
1
|
+
import process from"node:process";import{randomUUID}from"node:crypto";import{existsSync,renameSync,unlinkSync,writeFileSync}from"node:fs";import{bold,cyan,dim,green}from"@stacksjs/cli";import{projectPath,publicPath,storagePath}from"@stacksjs/path";import{seedCsrfPageResponse,validateDevCsrfRequest}from"./csrf";import{shouldDelegateDashboardRequest}from"./dashboard-request-routing";import{resolveDashboardCraftExecutable}from"./dashboard-native";import{buildManifest,discoverModels,findAvailablePort,waitForServer}from"./dashboard-utils";import{runDashboardSupervisor}from"./dashboard-supervisor";if(process.env.STACKS_DASHBOARD_WORKER!=="1"){const exitCode=await runDashboardSupervisor(import.meta.path,process.argv.slice(2));process.exit(exitCode)}const verboseIdx=process.argv.indexOf("--verbose"),verbose=verboseIdx!==-1&&process.argv[verboseIdx+1]!=="false",startTime=Bun.nanoseconds(),originalConsoleLog=console.log,originalConsoleWarn=console.warn,bufferedLogs=[];console.log=(...args)=>{bufferedLogs.push(args.map(String).join(" "))};console.warn=(...args)=>{bufferedLogs.push(args.map(String).join(" "))};const dashboardPath=storagePath("framework/defaults/views/dashboard"),userDashboardPath=projectPath("resources/views/dashboard"),preferredPort=Number(process.env.PORT_ADMIN)||3002,dashboardPort=await findAvailablePort(preferredPort),appUrl=process.env.APP_URL||"",hasCustomDomain=appUrl!==""&&appUrl!=="localhost"&&!appUrl.includes("localhost:"),domain=hasCustomDomain?appUrl.replace(/^https?:\/\//,""):null,dashboardDomain=domain?`dashboard.${domain}`:null,sslBasePath=`${process.env.HOME}/.stacks/ssl`;function restoreConsole(){console.log=originalConsoleLog;console.warn=(...args)=>{const msg=args.map(String).join(" ");if(msg.includes("[STX] DOM API violation")||msg.includes("unsafe expression"))return;originalConsoleWarn(...args)}}async function startStxServer(){await import("@stacksjs/orm");let serve;try{const localServe=process.env.BUN_PLUGIN_STX_SRC||`${process.env.HOME}/Code/Tools/stx/packages/bun-plugin/src/serve.ts`;if(!await Bun.file(localServe).exists())throw Error("local bun-plugin-stx source not found");serve=(await import(localServe)).serve}catch{try{serve=(await import("bun-plugin-stx/serve")).serve}catch{serve=(await import(projectPath("pantry/bun-plugin-stx/dist/serve.js"))).serve}}let stxModule;try{const localStx=process.env.STX_SRC||`${process.env.HOME}/Code/Tools/stx/packages/stx/src/index.ts`;if(await Bun.file(localStx).exists()){const localCrosswind=`${process.env.HOME}/Code/Tools/crosswind/packages/crosswind/src/index.ts`;if(!process.env.CROSSWIND_SRC&&await Bun.file(localCrosswind).exists())process.env.CROSSWIND_SRC=localCrosswind;stxModule=await import(localStx)}}catch{}if(stxModule&&verbose)console.log("[Dashboard] Using local stx checkout");if(!stxModule)try{const vendoredStx=projectPath("pantry/@stacksjs/stx/dist/index.js");if(await Bun.file(vendoredStx).exists())stxModule=await import(vendoredStx)}catch{}const{listConfigFiles,readConfig,updateConfigKeys}=await import(storagePath("framework/defaults/resources/functions/dashboard/config-io.ts")),localTsChartsRoot=process.env.TS_CHARTS_SRC||`${process.env.HOME}/Code/Libraries/ts-charts`,dependencyBundles=new Map;function resolveTsChartsSource(packageName){return[`${localTsChartsRoot}/packages/${packageName}/src/index.ts`,projectPath(`node_modules/@ts-charts/${packageName}/src/index.ts`),projectPath(`pantry/@ts-charts/${packageName}/src/index.ts`)].find(existsSync)||null}const tsChartsEntry=[`${localTsChartsRoot}/packages/ts-charts/src/index.ts`,projectPath("node_modules/ts-charts/src/index.ts"),projectPath("pantry/ts-charts/src/index.ts")].find(existsSync);async function buildDashboardDependency(entrypoint){const cached=dependencyBundles.get(entrypoint);if(cached)return cached;const build=(async()=>{const result=await Bun.build({entrypoints:[entrypoint],target:"browser",format:"esm",minify:!0,plugins:[{name:"dashboard-ts-charts-source",setup(builder){builder.onResolve({filter:/^@ts-charts\/[a-z0-9-]+$/},(args)=>{const packageName=args.path.slice(11),source=resolveTsChartsSource(packageName);if(source)return{path:source};return null})}}]});if(!result.success){const errors=result.logs.filter((log)=>log.level==="error").map((log)=>log.message).join(`
|
|
2
2
|
`);throw Error(errors||`Failed to bundle ${entrypoint}`)}const output=result.outputs.find((file)=>file.path.endsWith(".js"));if(!output)throw Error(`No JavaScript output produced for ${entrypoint}`);return output.text()})();dependencyBundles.set(entrypoint,build);return build}function browserDependencyRoute(entrypoint){return async()=>{try{return new Response(await buildDashboardDependency(entrypoint),{headers:{"content-type":"text/javascript; charset=utf-8","cache-control":"no-cache"}})}catch(error){dependencyBundles.delete(entrypoint);return new Response(`throw new Error(${JSON.stringify(error.message)})`,{status:500,headers:{"content-type":"text/javascript; charset=utf-8"}})}}}let dashboardIconCss=null;async function buildDashboardIconCss(){const{generateCss}=await import("@stacksjs/stx"),dirs=[dashboardPath,userDashboardPath,storagePath("framework/defaults/resources/components/Dashboard")],icons=new Set;for(const dir of dirs){if(!existsSync(dir))continue;const glob=new Bun.Glob("**/*.{stx,ts}");for await(const file of glob.scan({cwd:dir,absolute:!0})){const text=await Bun.file(file).text();for(const match of text.matchAll(/\bi-[a-z][a-z0-9]*(?:-[a-z0-9]+)+/g))icons.add(match[0])}}if(icons.size===0)return"";return generateCss(`<div class="${[...icons].join(" ")}"></div>`,process.cwd())}const configRoutes={"/__deps/charts.js":browserDependencyRoute(storagePath("framework/core/charts/src/index.ts")),"/__deps/ts-charts.js":browserDependencyRoute(tsChartsEntry||`${localTsChartsRoot}/packages/ts-charts/src/index.ts`),"/__deps/dashboard-icons.css":async()=>{if(!dashboardIconCss)dashboardIconCss=buildDashboardIconCss();return new Response(await dashboardIconCss,{headers:{"content-type":"text/css; charset=utf-8","cache-control":"no-cache"}})},"/api/config/list":async()=>{try{return Response.json({ok:!0,files:listConfigFiles()})}catch(e){return Response.json({ok:!1,error:e?.message},{status:500})}},"/api/config/read":async(req)=>{try{const name=new URL(req.url).searchParams.get("name")||"";if(!/^[\w-]+$/.test(name))return Response.json({ok:!1,error:"Invalid config name"},{status:400});const result=await readConfig(name);if(!result)return Response.json({ok:!1,error:"Not found"},{status:404});return Response.json({ok:!0,name,fields:result.fields})}catch(e){return Response.json({ok:!1,error:e?.message},{status:500})}},"/api/config/source":async(req)=>{try{const name=new URL(req.url).searchParams.get("name")||"";if(!/^[\w-]+$/.test(name))return Response.json({ok:!1,error:"Invalid config name"},{status:400});const result=await readConfig(name);if(!result)return Response.json({ok:!1,error:"Not found"},{status:404});return new Response(result.source,{headers:{"content-type":"text/plain; charset=utf-8"}})}catch(e){return Response.json({ok:!1,error:e?.message},{status:500})}},"/api/config/update":async(req)=>{if(req.method!=="POST")return Response.json({ok:!1,error:"Method not allowed"},{status:405});try{await validateDevCsrfRequest(req);const body=await req.json(),file=body.file?.replace(/\.ts$/,"");if(!file||!/^[\w-]+$/.test(file))return Response.json({ok:!1,error:"Invalid file"},{status:400});const updates=[];if(Array.isArray(body.updates))for(const u of body.updates){const k=u.key??u.path;if(typeof k==="string")updates.push({key:k,value:u.value})}else if(body.key)updates.push({key:body.key,value:body.value});if(updates.length===0)return Response.json({ok:!1,error:"No updates supplied"},{status:400});const invalid=updates.find((update)=>!/^[A-Za-z_$][\w$]*$/.test(update.key)||typeof update.value!=="string"&&typeof update.value!=="number"&&typeof update.value!=="boolean"||typeof update.value==="number"&&!Number.isFinite(update.value));if(invalid)return Response.json({ok:!1,error:`Invalid value for configuration key "${invalid.key}"`},{status:400});const typedUpdates=updates;try{await updateConfigKeys(file,typedUpdates)}catch(err){const error=err?.message||"Configuration values could not be updated.",results=typedUpdates.map((update)=>({key:update.key,ok:!1,error}));return Response.json({ok:!1,file,results,error},{status:422})}const results=typedUpdates.map((update)=>({key:update.key,ok:!0,newValue:update.value}));return Response.json({ok:!0,file,results})}catch(e){if(e?.status===403)return Response.json({ok:!1,error:"Forbidden",message:"CSRF token mismatch"},{status:403});return Response.json({ok:!1,error:e?.message},{status:500})}}},router=await import("@stacksjs/router"),routeRegistry=(await import(projectPath("app/Routes.ts"))).default;await router.loadRoutes(routeRegistry);const stacksRoute=router.route;serve({root:projectPath("resources"),patterns:[userDashboardPath,dashboardPath],port:dashboardPort,componentsDir:storagePath("framework/defaults/resources/components/Dashboard"),layoutsDir:dashboardPath,partialsDir:dashboardPath,publicDir:publicPath(),renderCache:!0,renderCacheVary:"source",prewarmRenderCache:4,watchDirs:[projectPath("resources/functions"),storagePath("framework/defaults/resources/functions")],quiet:!0,routes:configRoutes,onRequest:async(req)=>{const pathname=new URL(req.url).pathname;if(shouldDelegateDashboardRequest(pathname,req.method))return stacksRoute.handleRequest(req);return null},onResponse:seedCsrfPageResponse,auth:!1,...stxModule&&{stxModule}}).catch((err)=>{restoreConsole();console.error(`
|
|
3
3
|
Failed to start dashboard server: ${err?.message||err}
|
|
4
4
|
`);process.exit(1)})}async function startReverseProxy(){if(!dashboardDomain)return!1;if(process.env.STACKS_PROXY_MANAGED)return!1;try{const{startProxies}=await import("@stacksjs/rpx");await startProxies({proxies:[{from:`localhost:${dashboardPort}`,to:dashboardDomain,cleanUrls:!1}],https:{basePath:sslBasePath,validityDays:825},regenerateUntrustedCerts:!1,verbose});return!0}catch(error){if(verbose)originalConsoleLog(` ${dim(`Proxy: ${error}`)}`);return!1}}const[,discoveredModels]=await Promise.all([startStxServer(),discoverModels(projectPath("app/Models"),storagePath("framework/defaults/app/Models"))]),{loadDashboardConfig}=await import(storagePath("framework/defaults/resources/functions/dashboard/toggles.ts")),{toggles:dashboardToggles,nav:dashboardNav}=await loadDashboardConfig(projectPath("config/dashboard.ts")),manifestPath=storagePath("framework/defaults/views/dashboard/.discovered-models.json"),manifestPayload={models:buildManifest(discoveredModels),sections:dashboardToggles,nav:dashboardNav},manifestTempPath=`${manifestPath}.${process.pid}.${randomUUID()}.tmp`;try{writeFileSync(manifestTempPath,JSON.stringify(manifestPayload,null,2),{flag:"wx"});renameSync(manifestTempPath,manifestPath)}finally{if(existsSync(manifestTempPath))unlinkSync(manifestTempPath)}const serverReady=await waitForServer(dashboardPort);restoreConsole();let proxyStarted=Boolean(process.env.STACKS_PROXY_MANAGED);if(!proxyStarted)proxyStarted=await startReverseProxy().catch((err)=>{if(verbose)console.warn("[Dashboard] Reverse proxy failed:",err);return!1});const dashboardHttpsUrl=dashboardDomain?`https://${dashboardDomain}`:null,dashboardLocalUrl=`http://localhost:${dashboardPort}`,initialUrl=dashboardHttpsUrl&&proxyStarted?`${dashboardHttpsUrl}/`:`${dashboardLocalUrl}/`,elapsedMs=(Bun.nanoseconds()-startTime)/1e6;console.log();console.log(` ${bold(cyan("stacks dashboard"))}`);console.log();if(dashboardHttpsUrl){console.log(` ${green("\u279C")} ${bold("Local")}: ${cyan(dashboardHttpsUrl)}`);console.log(` ${dim("\u279C")} ${dim("Origin")}: ${dim(dashboardLocalUrl)}`)}else console.log(` ${green("\u279C")} ${bold("Local")}: ${cyan(dashboardLocalUrl)}`);console.log(` ${green("\u279C")} ${bold("Window")}: ${dim("Stacks Dashboard")} ${dim("1400\xD7900")}`);console.log(` ${green("\u279C")} ${bold("Models")}: ${dim(`${discoveredModels.length} discovered`)}`);if(dashboardPort!==preferredPort)console.log(` ${dim("\u279C")} ${dim(`Port ${preferredPort} in use, using ${dashboardPort}`)}`);if(!serverReady)console.log(` ${dim("\u26A0")} ${dim("Dev server may not be ready yet")}`);console.log();console.log(` ${dim(`ready in ${elapsedMs.toFixed(0)} ms`)}`);if(verbose){console.log();console.log(` ${dim("\u279C")} ${dim("URL")}: ${dim(initialUrl)}`);if(dashboardDomain){console.log(` ${dim("\u279C")} ${dim("SSL")}: ${dim(sslBasePath)}`);console.log(` ${dim("\u279C")} ${dim("Proxy")}: ${dim(`localhost:${dashboardPort} \u2192 ${dashboardDomain}`)}`)}if(bufferedLogs.length>0){console.log();for(const line of bufferedLogs)console.log(` ${dim(line)}`)}}console.log();let createApp,resolveCraftBinary;const nativeDisabled=process.env.STACKS_NO_NATIVE==="1",explicitCraftSdk=process.env.CRAFT_SDK_SRC;if(!nativeDisabled&&explicitCraftSdk){if(!existsSync(explicitCraftSdk))throw Error(`CRAFT_SDK_SRC not found: ${explicitCraftSdk}`);try{({createApp,resolveCraftBinary}=await import(explicitCraftSdk));if(!createApp||!resolveCraftBinary)throw Error("CRAFT_SDK_SRC must export createApp and resolveCraftBinary")}catch(error){throw Error(`Could not load CRAFT_SDK_SRC ${explicitCraftSdk}: ${error instanceof Error?error.message:String(error)}`)}}if(!nativeDisabled&&!explicitCraftSdk)try{({createApp,resolveCraftBinary}=await import("craft-native"))}catch{}const craftBinaryPath=createApp&&resolveCraftBinary?resolveDashboardCraftExecutable(resolveCraftBinary):void 0;if(createApp&&craftBinaryPath){const userIconPath=projectPath("resources/assets/images/app-icon.png"),defaultIconPath=storagePath("framework/defaults/resources/assets/images/app-icon.png"),appIconPath=await Bun.file(userIconPath).exists()?userIconPath:await Bun.file(defaultIconPath).exists()?defaultIconPath:void 0,app=createApp({url:dashboardLocalUrl,quiet:!verbose,craftPath:craftBinaryPath,window:{title:"Stacks Dashboard",width:1400,height:900,titlebarHidden:!0,webSidebarMaterial:!0,webSidebarWidth:250,...appIconPath&&{icon:appIconPath}}});process.on("SIGINT",()=>{app.close();process.exit(0)});process.on("SIGTERM",()=>{app.close();process.exit(0)});try{await app.show();process.exit(0)}catch(error){const fallbackUrl=dashboardHttpsUrl||dashboardLocalUrl;console.log(` ${dim("Native Craft window failed:")} ${dim(error instanceof Error?error.message:String(error))}`);console.log(` ${dim("Dashboard available at:")} ${cyan(fallbackUrl)}
|
package/dist/queue/failed.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import process from"node:process";import{log}from"@stacksjs/logging";import{FailedJob}from"@stacksjs/orm";const options=parseArgs(),
|
|
1
|
+
import process from"node:process";import{log}from"@stacksjs/logging";import{FailedJob}from"@stacksjs/orm";const options=parseArgs(),queueName=options.queue,sinceArg=options.since,sinceCutoff=sinceArg?parseSinceDuration(sinceArg):null;try{log.info(`Fetching failed jobs...
|
|
2
2
|
`);let failedJobs;if(queueName)failedJobs=await FailedJob.where("queue",queueName).get();else failedJobs=await FailedJob.all();if(sinceCutoff)failedJobs=failedJobs.filter((j)=>{if(!j.failed_at)return!1;const ts=Date.parse(j.failed_at);return Number.isFinite(ts)&&ts>=sinceCutoff});if(failedJobs.length===0){if(sinceCutoff)console.log(`\u2713 No failed jobs found since ${sinceArg}`);else console.log("\u2713 No failed jobs found");process.exit(0)}console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");console.log("\u2502 ID \u2502 Queue \u2502 Failed At \u2502 Exception \u2502");console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");for(const job of failedJobs){const id=String(job.id).padEnd(3),queue=(job.queue||"default").substring(0,48).padEnd(48),failedAt=(job.failed_at||"N/A").substring(0,21).padEnd(21),exception=(job.exception||"Unknown error").substring(0,31).padEnd(31);console.log(`\u2502 ${id} \u2502 ${queue} \u2502 ${failedAt} \u2502 ${exception} \u2502`)}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");console.log(`
|
|
3
3
|
Total: ${failedJobs.length} failed job(s)`);process.exit(0)}catch(error){const message=error instanceof Error?error.message:String(error);if(/no such table:\s*(?:jobs|failed_jobs)\b/i.test(message)){process.stdout.write(`Queue tables are not set up yet.
|
|
4
4
|
`);process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");process.exit(0)}await log.error("Failed to fetch failed jobs",error);process.exit(1)}function parseArgs(){const args={};process.argv.forEach((arg)=>{if(arg.startsWith("--")){const[key,value]=arg.slice(2).split("=");if(key&&value)args[key]=value}});return args}function parseSinceDuration(input){const m=/^(\d+)([smhd])$/.exec(input.trim());if(!m)return null;const n=Number(m[1]);if(!Number.isFinite(n)||n<=0)return null;const mult=m[2]==="s"?1000:m[2]==="m"?60000:m[2]==="h"?3600000:86400000;return Date.now()-n*mult}
|
package/dist/queue/list.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import process from"node:process";import{log}from"@stacksjs/logging";import{Job}from"@stacksjs/orm";const options=parseArgs(),
|
|
1
|
+
import process from"node:process";import{log}from"@stacksjs/logging";import{Job}from"@stacksjs/orm";const options=parseArgs(),queueName=options.queue,statusFilter=options.status,limit=options.limit?Number.parseInt(options.limit,10):50;try{log.info(`Fetching queued jobs...
|
|
2
2
|
`);let jobs=queueName?await Job.where("queue",queueName).get():await Job.all();const nowSec=Math.floor(Date.now()/1000);if(statusFilter==="pending")jobs=jobs.filter((j)=>!j.reserved_at&&(j.available_at??0)<=nowSec);else if(statusFilter==="reserved")jobs=jobs.filter((j)=>Boolean(j.reserved_at));else if(statusFilter==="delayed")jobs=jobs.filter((j)=>!j.reserved_at&&(j.available_at??0)>nowSec);if(Number.isFinite(limit)&&limit>0)jobs=jobs.slice(0,limit);if(jobs.length===0){console.log("\u2713 No queued jobs found");process.exit(0)}console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");console.log("\u2502 ID \u2502 Queue \u2502 Job \u2502 Attempts \u2502 Status \u2502 Available At \u2502");console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");for(const j of jobs){const jobAny=j,id=String(jobAny.id??"").padEnd(3),queue=String(jobAny.queue??"default").substring(0,18).padEnd(18),jobName=extractJobName(jobAny.payload).substring(0,32).padEnd(32),attempts=String(jobAny.attempts??0).padEnd(8),status=(jobAny.reserved_at?"reserved":(jobAny.available_at??0)>nowSec?"delayed":"pending").padEnd(8),avail=formatUnixTime(jobAny.available_at).padEnd(19);console.log(`\u2502 ${id} \u2502 ${queue} \u2502 ${jobName} \u2502 ${attempts} \u2502 ${status} \u2502 ${avail} \u2502`)}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");console.log(`
|
|
3
3
|
Showing ${jobs.length} job(s)${queueName?` on queue '${queueName}'`:""}${statusFilter?` (status=${statusFilter})`:""}`);process.exit(0)}catch(error){const message=error instanceof Error?error.message:String(error);if(/no such table:\s*jobs\b/i.test(message)){process.stdout.write(`Queue tables are not set up yet.
|
|
4
4
|
`);process.stdout.write("Run `buddy queue:table` to create the migrations, then `buddy migrate` to apply them.\n");process.exit(0)}await log.error("Failed to list queued jobs",error);process.exit(1)}function extractJobName(payload){if(typeof payload!=="string")return"unknown";try{const parsed=JSON.parse(payload);return parsed.jobName??parsed.name??"unknown"}catch{return"unknown"}}function formatUnixTime(seconds){if(typeof seconds!=="number"||!Number.isFinite(seconds))return"N/A";return new Date(seconds*1000).toISOString().slice(0,19).replace("T"," ")}function parseArgs(){const args={};process.argv.forEach((arg)=>{if(arg.startsWith("--")){const[key,value]=arg.slice(2).split("=");if(key&&value)args[key]=value}});return args}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/actions",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.74.
|
|
5
|
+
"version": "0.74.35",
|
|
6
6
|
"description": "The Stacks actions.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -60,51 +60,51 @@
|
|
|
60
60
|
"prepublishOnly": "bun run build"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@stacksjs/action-runner": "0.74.
|
|
64
|
-
"@stacksjs/ai": "0.74.
|
|
65
|
-
"@stacksjs/analytics": "0.74.
|
|
66
|
-
"@stacksjs/api": "0.74.
|
|
67
|
-
"@stacksjs/auth": "0.74.
|
|
68
|
-
"@stacksjs/build": "0.74.
|
|
63
|
+
"@stacksjs/action-runner": "0.74.35",
|
|
64
|
+
"@stacksjs/ai": "0.74.35",
|
|
65
|
+
"@stacksjs/analytics": "0.74.35",
|
|
66
|
+
"@stacksjs/api": "0.74.35",
|
|
67
|
+
"@stacksjs/auth": "0.74.35",
|
|
68
|
+
"@stacksjs/build": "0.74.35",
|
|
69
69
|
"@stacksjs/bumpx": "^0.2.6",
|
|
70
70
|
"@stacksjs/bunpress": "^0.2.8",
|
|
71
|
-
"@stacksjs/cli": "0.74.
|
|
72
|
-
"@stacksjs/cloud": "0.74.
|
|
73
|
-
"@stacksjs/cms": "0.74.
|
|
74
|
-
"@stacksjs/config": "0.74.
|
|
75
|
-
"@stacksjs/database": "0.74.
|
|
76
|
-
"@stacksjs/desktop-build": "0.74.
|
|
77
|
-
"@stacksjs/dns": "0.74.
|
|
78
|
-
"@stacksjs/enums": "0.74.
|
|
79
|
-
"@stacksjs/env": "0.74.
|
|
80
|
-
"@stacksjs/error-handling": "0.74.
|
|
71
|
+
"@stacksjs/cli": "0.74.35",
|
|
72
|
+
"@stacksjs/cloud": "0.74.35",
|
|
73
|
+
"@stacksjs/cms": "0.74.35",
|
|
74
|
+
"@stacksjs/config": "0.74.35",
|
|
75
|
+
"@stacksjs/database": "0.74.35",
|
|
76
|
+
"@stacksjs/desktop-build": "0.74.35",
|
|
77
|
+
"@stacksjs/dns": "0.74.35",
|
|
78
|
+
"@stacksjs/enums": "0.74.35",
|
|
79
|
+
"@stacksjs/env": "0.74.35",
|
|
80
|
+
"@stacksjs/error-handling": "0.74.35",
|
|
81
81
|
"@stacksjs/gitit": "^0.2.5",
|
|
82
|
-
"@stacksjs/i18n": "0.74.
|
|
83
|
-
"@stacksjs/image": "0.74.
|
|
84
|
-
"@stacksjs/logging": "0.74.
|
|
82
|
+
"@stacksjs/i18n": "0.74.35",
|
|
83
|
+
"@stacksjs/image": "0.74.35",
|
|
84
|
+
"@stacksjs/logging": "0.74.35",
|
|
85
85
|
"@stacksjs/logsmith": "^0.2.3",
|
|
86
|
-
"@stacksjs/orm": "0.74.
|
|
87
|
-
"@stacksjs/path": "0.74.
|
|
88
|
-
"@stacksjs/payments": "0.74.
|
|
89
|
-
"@stacksjs/queue": "0.74.
|
|
90
|
-
"@stacksjs/registry": "0.74.
|
|
91
|
-
"@stacksjs/router": "0.74.
|
|
92
|
-
"@stacksjs/rpx": "^0.11.
|
|
93
|
-
"@stacksjs/scheduler": "0.74.
|
|
94
|
-
"@stacksjs/search-engine": "0.74.
|
|
95
|
-
"@stacksjs/security": "0.74.
|
|
96
|
-
"@stacksjs/server": "0.74.
|
|
97
|
-
"@stacksjs/sites": "0.74.
|
|
98
|
-
"@stacksjs/storage": "0.74.
|
|
99
|
-
"@stacksjs/strings": "0.74.
|
|
86
|
+
"@stacksjs/orm": "0.74.35",
|
|
87
|
+
"@stacksjs/path": "0.74.35",
|
|
88
|
+
"@stacksjs/payments": "0.74.35",
|
|
89
|
+
"@stacksjs/queue": "0.74.35",
|
|
90
|
+
"@stacksjs/registry": "0.74.35",
|
|
91
|
+
"@stacksjs/router": "0.74.35",
|
|
92
|
+
"@stacksjs/rpx": "^0.11.53",
|
|
93
|
+
"@stacksjs/scheduler": "0.74.35",
|
|
94
|
+
"@stacksjs/search-engine": "0.74.35",
|
|
95
|
+
"@stacksjs/security": "0.74.35",
|
|
96
|
+
"@stacksjs/server": "0.74.35",
|
|
97
|
+
"@stacksjs/sites": "0.74.35",
|
|
98
|
+
"@stacksjs/storage": "0.74.35",
|
|
99
|
+
"@stacksjs/strings": "0.74.35",
|
|
100
100
|
"@stacksjs/stx": "^0.2.284",
|
|
101
101
|
"@stacksjs/tlsx": "^0.13.19",
|
|
102
|
-
"@stacksjs/ts-cloud": "^0.
|
|
102
|
+
"@stacksjs/ts-cloud": "^0.13.1",
|
|
103
103
|
"@stacksjs/ts-md": "^0.1.1",
|
|
104
|
-
"@stacksjs/tunnel": "0.74.
|
|
105
|
-
"@stacksjs/types": "0.74.
|
|
106
|
-
"@stacksjs/utils": "0.74.
|
|
107
|
-
"@stacksjs/whois": "0.74.
|
|
104
|
+
"@stacksjs/tunnel": "0.74.35",
|
|
105
|
+
"@stacksjs/types": "0.74.35",
|
|
106
|
+
"@stacksjs/utils": "0.74.35",
|
|
107
|
+
"@stacksjs/whois": "0.74.35",
|
|
108
108
|
"bun-plugin-stx": "^0.2.279"
|
|
109
109
|
},
|
|
110
110
|
"peerDependencies": {
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
}
|
|
121
121
|
},
|
|
122
122
|
"devDependencies": {
|
|
123
|
-
"@stacksjs/validation": "0.74.
|
|
123
|
+
"@stacksjs/validation": "0.74.35",
|
|
124
124
|
"better-dx": "^0.2.24"
|
|
125
125
|
}
|
|
126
126
|
}
|