windsor-bot 0.2.5 → 0.2.7

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/printer.js CHANGED
@@ -57,12 +57,7 @@ function chooseFontForLines(totalLines) {
57
57
  }
58
58
  }
59
59
  function countLayoutLines(lines) {
60
- const longestLine = lines.reduce((max, line) => Math.max(max, line.length), 0);
61
- return longestLine > CHARS_DOUBLE
62
- ? 9
63
- : lines.length <= 2
64
- ? 2
65
- : lines.length;
60
+ return lines.length <= 2 ? 2 : lines.length;
66
61
  }
67
62
  export async function getConnectedPrinter() {
68
63
  // Try CUPS first
@@ -35,12 +35,7 @@ function chooseFontForLines(totalLines) {
35
35
  }
36
36
  }
37
37
  function countLayoutLines(lines) {
38
- const longestLine = lines.reduce((max, line) => Math.max(max, line.length), 0);
39
- return longestLine > COLS_DOUBLE
40
- ? 9
41
- : lines.length <= 2
42
- ? 2
43
- : lines.length;
38
+ return lines.length <= 2 ? 2 : lines.length;
44
39
  }
45
40
  export async function buildEscpBuffer(job) {
46
41
  const conn = new InMemory();
@@ -22,12 +22,7 @@ function chooseLineHeight(totalLines) {
22
22
  return { lineHeight: LINE_HEIGHT_NORMAL, fontPath: FONT_16 };
23
23
  }
24
24
  function countLayoutLines(lines) {
25
- const longestLine = lines.reduce((max, line) => Math.max(max, line.length), 0);
26
- return longestLine > 24
27
- ? 9
28
- : lines.length <= 2
29
- ? 2
30
- : lines.length;
25
+ return lines.length <= 2 ? 2 : lines.length;
31
26
  }
32
27
  function wrapText(text, font, maxWidth) {
33
28
  if (!text)
package/dist/server.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createServer } from 'http';
2
2
  import { execFile } from 'child_process';
3
3
  import { build } from 'esbuild';
4
- import { access, readFile, stat } from 'fs/promises';
4
+ import { access, constants, readFile, stat } from 'fs/promises';
5
5
  import { promisify } from 'util';
6
6
  import { spawn } from 'child_process';
7
7
  import { dirname, join } from 'path';
@@ -65,7 +65,7 @@ async function readPackageVersion() {
65
65
  return packageJson.version;
66
66
  }
67
67
  async function updateGlobalBot() {
68
- const npmCandidates = [
68
+ const configuredCandidates = [
69
69
  process.env['npm_execpath'],
70
70
  join(dirname(process.execPath), '..', 'lib', 'node_modules', 'npm', 'bin', 'npm-cli.js'),
71
71
  join(dirname(process.execPath), 'npm'),
@@ -76,11 +76,17 @@ async function updateGlobalBot() {
76
76
  '/usr/local/bin/npm',
77
77
  '/opt/homebrew/bin/npm',
78
78
  '/usr/bin/npm',
79
- 'npm',
80
79
  ]
81
80
  .filter((candidate) => Boolean(candidate))
82
81
  .map(candidate => candidate.trim())
83
82
  .filter((candidate, index, candidates) => candidates.indexOf(candidate) === index);
83
+ const pathCandidates = (process.env['PATH'] ?? '')
84
+ .split(':')
85
+ .filter(Boolean)
86
+ .map(directory => join(directory, 'npm'));
87
+ const npmCandidates = [...configuredCandidates, ...pathCandidates]
88
+ .filter((candidate, index, candidates) => candidates.indexOf(candidate) === index);
89
+ logEvent('info', `Update requested; checking ${npmCandidates.length} npm candidate(s) (node=${process.execPath}, cwd=${process.cwd()})`);
84
90
  let npmCommand;
85
91
  for (const candidate of npmCandidates) {
86
92
  const command = candidate.endsWith('.js')
@@ -88,19 +94,40 @@ async function updateGlobalBot() {
88
94
  : { path: candidate, args: [] };
89
95
  try {
90
96
  // Validate the script itself, not just the Node executable used to run it.
91
- if (candidate !== 'npm')
92
- await access(candidate);
97
+ await access(candidate, constants.R_OK | (candidate.endsWith('.js') ? 0 : constants.X_OK));
93
98
  npmCommand = command;
99
+ logEvent('info', `Using npm candidate ${candidate}${command.args.length > 0 ? ` via ${command.path}` : ''}`);
94
100
  break;
95
101
  }
96
- catch {
97
- // Try the next known npm installation location.
102
+ catch (error) {
103
+ const code = error instanceof Error && 'code' in error ? String(error.code) : 'unknown';
104
+ logEvent('info', `npm candidate unavailable: ${candidate} (${code})`);
98
105
  }
99
106
  }
100
- if (!npmCommand)
101
- throw new Error('Unable to locate npm');
107
+ if (!npmCommand) {
108
+ const path = process.env['PATH'] ?? '(unset)';
109
+ logEvent('error', `Unable to locate an executable npm; PATH=${path}`);
110
+ throw new Error('Unable to locate an executable npm; see diagnostics');
111
+ }
102
112
  const npm = npmCommand;
103
- const runNpm = (args) => execFileAsync(npm.path, [...npm.args, ...args], { env: process.env });
113
+ const runNpm = async (args) => {
114
+ const commandArgs = [...npm.args, ...args];
115
+ logEvent('info', `Running npm: ${npm.path} ${commandArgs.join(' ')}`);
116
+ try {
117
+ const result = await execFileAsync(npm.path, commandArgs, { env: process.env });
118
+ logEvent('info', `npm completed successfully: ${args.join(' ')}`);
119
+ return result;
120
+ }
121
+ catch (error) {
122
+ const details = error instanceof Error ? error : new Error(String(error));
123
+ const code = 'code' in details ? String(details.code) : 'unknown';
124
+ const stderr = 'stderr' in details && typeof details.stderr === 'string'
125
+ ? details.stderr.trim().slice(-1000)
126
+ : '';
127
+ logEvent('error', `npm failed (code=${code}, path=${npm.path}, args=${commandArgs.join(' ')})${stderr ? ` stderr=${stderr}` : ''}`);
128
+ throw details;
129
+ }
130
+ };
104
131
  await runNpm(['install', '-g', 'windsor-bot@latest']);
105
132
  const { stdout } = await runNpm(['root', '-g']);
106
133
  const packageJsonPath = join(stdout.trim(), 'windsor-bot', 'package.json');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windsor-bot",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Self-hosted Discord bot automation for household list and todo printing",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",