@karmaniverous/jeeves-runner 0.1.0 → 0.1.2

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,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { mkdirSync, readFileSync } from 'node:fs';
3
- import { dirname, resolve } from 'node:path';
3
+ import { dirname, extname, resolve } from 'node:path';
4
4
  import { Command } from 'commander';
5
5
  import { DatabaseSync } from 'node:sqlite';
6
6
  import { pino } from 'pino';
@@ -406,6 +406,23 @@ function parseResultLines(stdout) {
406
406
  }
407
407
  return { tokens, resultMeta };
408
408
  }
409
+ /** Resolve the command and arguments for a script based on its file extension. */
410
+ function resolveCommand(script) {
411
+ const ext = extname(script).toLowerCase();
412
+ switch (ext) {
413
+ case '.ps1':
414
+ return {
415
+ command: 'powershell.exe',
416
+ args: ['-NoProfile', '-File', script],
417
+ };
418
+ case '.cmd':
419
+ case '.bat':
420
+ return { command: 'cmd.exe', args: ['/c', script] };
421
+ default:
422
+ // .js, .mjs, .cjs, or anything else: run with node
423
+ return { command: 'node', args: [script] };
424
+ }
425
+ }
409
426
  /**
410
427
  * Execute a job script as a child process. Captures output, parses metadata, enforces timeout.
411
428
  */
@@ -415,7 +432,8 @@ function executeJob(options) {
415
432
  return new Promise((resolve) => {
416
433
  const stdoutBuffer = new RingBuffer(100);
417
434
  const stderrBuffer = new RingBuffer(100);
418
- const child = spawn('node', [script], {
435
+ const { command, args } = resolveCommand(script);
436
+ const child = spawn(command, args, {
419
437
  env: {
420
438
  ...process.env,
421
439
  JR_DB_PATH: dbPath,
@@ -604,8 +622,17 @@ function createScheduler(deps) {
604
622
  logger.info({ count: jobs.length }, 'Loading jobs');
605
623
  for (const job of jobs) {
606
624
  try {
625
+ const jobId = job.id;
607
626
  const cron = new Cron(job.schedule, () => {
608
- void onScheduledRun(job);
627
+ // Re-read job from DB to get current configuration
628
+ const currentJob = db
629
+ .prepare('SELECT * FROM jobs WHERE id = ? AND enabled = 1')
630
+ .get(jobId);
631
+ if (!currentJob) {
632
+ logger.warn({ jobId }, 'Job no longer exists or disabled, skipping');
633
+ return;
634
+ }
635
+ void onScheduledRun(currentJob);
609
636
  });
610
637
  crons.set(job.id, cron);
611
638
  logger.info({ jobId: job.id, schedule: job.schedule }, 'Scheduled job');
package/dist/mjs/index.js CHANGED
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import { mkdirSync, readFileSync } from 'node:fs';
3
3
  import { pino } from 'pino';
4
4
  import Fastify from 'fastify';
5
- import { dirname } from 'node:path';
5
+ import { dirname, extname } from 'node:path';
6
6
  import { DatabaseSync } from 'node:sqlite';
7
7
  import { request } from 'node:https';
8
8
  import { spawn } from 'node:child_process';
@@ -486,6 +486,23 @@ function parseResultLines(stdout) {
486
486
  }
487
487
  return { tokens, resultMeta };
488
488
  }
489
+ /** Resolve the command and arguments for a script based on its file extension. */
490
+ function resolveCommand(script) {
491
+ const ext = extname(script).toLowerCase();
492
+ switch (ext) {
493
+ case '.ps1':
494
+ return {
495
+ command: 'powershell.exe',
496
+ args: ['-NoProfile', '-File', script],
497
+ };
498
+ case '.cmd':
499
+ case '.bat':
500
+ return { command: 'cmd.exe', args: ['/c', script] };
501
+ default:
502
+ // .js, .mjs, .cjs, or anything else: run with node
503
+ return { command: 'node', args: [script] };
504
+ }
505
+ }
489
506
  /**
490
507
  * Execute a job script as a child process. Captures output, parses metadata, enforces timeout.
491
508
  */
@@ -495,7 +512,8 @@ function executeJob(options) {
495
512
  return new Promise((resolve) => {
496
513
  const stdoutBuffer = new RingBuffer(100);
497
514
  const stderrBuffer = new RingBuffer(100);
498
- const child = spawn('node', [script], {
515
+ const { command, args } = resolveCommand(script);
516
+ const child = spawn(command, args, {
499
517
  env: {
500
518
  ...process.env,
501
519
  JR_DB_PATH: dbPath,
@@ -684,8 +702,17 @@ function createScheduler(deps) {
684
702
  logger.info({ count: jobs.length }, 'Loading jobs');
685
703
  for (const job of jobs) {
686
704
  try {
705
+ const jobId = job.id;
687
706
  const cron = new Cron(job.schedule, () => {
688
- void onScheduledRun(job);
707
+ // Re-read job from DB to get current configuration
708
+ const currentJob = db
709
+ .prepare('SELECT * FROM jobs WHERE id = ? AND enabled = 1')
710
+ .get(jobId);
711
+ if (!currentJob) {
712
+ logger.warn({ jobId }, 'Job no longer exists or disabled, skipping');
713
+ return;
714
+ }
715
+ void onScheduledRun(currentJob);
689
716
  });
690
717
  crons.set(job.id, cron);
691
718
  logger.info({ jobId: job.id, schedule: job.schedule }, 'Scheduled job');
package/package.json CHANGED
@@ -137,5 +137,5 @@
137
137
  },
138
138
  "type": "module",
139
139
  "types": "dist/index.d.ts",
140
- "version": "0.1.0"
140
+ "version": "0.1.2"
141
141
  }