@amaster.ai/pi-shared 0.1.2-beta.44 → 0.1.2-beta.46
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/package.json +1 -5
- package/dist/__tests__/scheduler.test.d.ts +0 -2
- package/dist/__tests__/scheduler.test.d.ts.map +0 -1
- package/dist/__tests__/scheduler.test.js +0 -219
- package/dist/__tests__/scheduler.test.js.map +0 -1
- package/dist/scheduler.d.ts +0 -14
- package/dist/scheduler.d.ts.map +0 -1
- package/dist/scheduler.js +0 -235
- package/dist/scheduler.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amaster.ai/pi-shared",
|
|
3
|
-
"version": "0.1.2-beta.
|
|
3
|
+
"version": "0.1.2-beta.46",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -15,10 +15,6 @@
|
|
|
15
15
|
"types": "./dist/settings.d.ts",
|
|
16
16
|
"default": "./dist/settings.js"
|
|
17
17
|
},
|
|
18
|
-
"./scheduler": {
|
|
19
|
-
"types": "./dist/scheduler.d.ts",
|
|
20
|
-
"default": "./dist/scheduler.js"
|
|
21
|
-
},
|
|
22
18
|
"./package.json": {
|
|
23
19
|
"default": "./package.json"
|
|
24
20
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/scheduler.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
|
|
2
|
-
import { tmpdir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
-
// Mock child_process and os/fs so we don't actually touch the system scheduler
|
|
6
|
-
const execFileSyncMock = vi.fn();
|
|
7
|
-
vi.mock('node:child_process', () => ({
|
|
8
|
-
execFileSync: (...args) => execFileSyncMock(...args),
|
|
9
|
-
}));
|
|
10
|
-
let mockedHome;
|
|
11
|
-
vi.mock('node:os', async (importOriginal) => {
|
|
12
|
-
const actual = await importOriginal();
|
|
13
|
-
return {
|
|
14
|
-
...actual,
|
|
15
|
-
homedir: () => mockedHome,
|
|
16
|
-
};
|
|
17
|
-
});
|
|
18
|
-
describe('scheduler', () => {
|
|
19
|
-
let tempDir;
|
|
20
|
-
let originalPlatform;
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
tempDir = join(tmpdir(), `pi-scheduler-test-${Date.now()}`);
|
|
23
|
-
mkdirSync(tempDir, { recursive: true });
|
|
24
|
-
mockedHome = tempDir;
|
|
25
|
-
execFileSyncMock.mockReset();
|
|
26
|
-
});
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
29
|
-
if (originalPlatform) {
|
|
30
|
-
Object.defineProperty(process, 'platform', originalPlatform);
|
|
31
|
-
originalPlatform = undefined;
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
function setPlatform(platform) {
|
|
35
|
-
originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
|
|
36
|
-
Object.defineProperty(process, 'platform', { value: platform, writable: true });
|
|
37
|
-
}
|
|
38
|
-
describe('darwin (launchd)', () => {
|
|
39
|
-
beforeEach(() => setPlatform('darwin'));
|
|
40
|
-
it('install writes plist and calls launchctl load', async () => {
|
|
41
|
-
const { install } = await import('../scheduler.js');
|
|
42
|
-
await install({
|
|
43
|
-
name: 'ai.pi.test-job',
|
|
44
|
-
command: '/usr/bin/node',
|
|
45
|
-
args: ['/path/to/script.js', '--once'],
|
|
46
|
-
intervalSeconds: 14400,
|
|
47
|
-
description: 'Test job',
|
|
48
|
-
});
|
|
49
|
-
const plistDir = join(tempDir, 'Library', 'LaunchAgents');
|
|
50
|
-
const plistPath = join(plistDir, 'ai.pi.test-job.plist');
|
|
51
|
-
expect(existsSync(plistPath)).toBe(true);
|
|
52
|
-
const content = readFileSync(plistPath, 'utf-8');
|
|
53
|
-
expect(content).toContain('<string>ai.pi.test-job</string>');
|
|
54
|
-
expect(content).toContain('<string>/usr/bin/node</string>');
|
|
55
|
-
expect(content).toContain('<string>/path/to/script.js</string>');
|
|
56
|
-
expect(content).toContain('<string>--once</string>');
|
|
57
|
-
expect(content).toContain('<integer>14400</integer>');
|
|
58
|
-
expect(execFileSyncMock).toHaveBeenCalledWith('launchctl', ['load', '-w', plistPath], {
|
|
59
|
-
stdio: 'ignore',
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
it('uninstall calls launchctl unload and removes plist', async () => {
|
|
63
|
-
const { install, uninstall } = await import('../scheduler.js');
|
|
64
|
-
await install({
|
|
65
|
-
name: 'ai.pi.test-job',
|
|
66
|
-
command: '/usr/bin/node',
|
|
67
|
-
args: ['/path/to/script.js'],
|
|
68
|
-
intervalSeconds: 3600,
|
|
69
|
-
});
|
|
70
|
-
execFileSyncMock.mockReset();
|
|
71
|
-
await uninstall('ai.pi.test-job');
|
|
72
|
-
const plistPath = join(tempDir, 'Library', 'LaunchAgents', 'ai.pi.test-job.plist');
|
|
73
|
-
expect(existsSync(plistPath)).toBe(false);
|
|
74
|
-
expect(execFileSyncMock).toHaveBeenCalledWith('launchctl', ['unload', plistPath], {
|
|
75
|
-
stdio: 'ignore',
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
it('status returns installed when plist exists', async () => {
|
|
79
|
-
const { install, status } = await import('../scheduler.js');
|
|
80
|
-
expect(await status('ai.pi.test-job')).toBe('not-found');
|
|
81
|
-
await install({
|
|
82
|
-
name: 'ai.pi.test-job',
|
|
83
|
-
command: '/usr/bin/node',
|
|
84
|
-
args: ['script.js'],
|
|
85
|
-
intervalSeconds: 7200,
|
|
86
|
-
});
|
|
87
|
-
expect(await status('ai.pi.test-job')).toBe('installed');
|
|
88
|
-
});
|
|
89
|
-
it('uninstall is no-op when plist does not exist', async () => {
|
|
90
|
-
const { uninstall } = await import('../scheduler.js');
|
|
91
|
-
await uninstall('ai.pi.nonexistent');
|
|
92
|
-
expect(execFileSyncMock).not.toHaveBeenCalled();
|
|
93
|
-
});
|
|
94
|
-
it('status returns not-found when plist exists but launchctl list fails', async () => {
|
|
95
|
-
const { install, status } = await import('../scheduler.js');
|
|
96
|
-
await install({
|
|
97
|
-
name: 'ai.pi.test-job',
|
|
98
|
-
command: '/usr/bin/node',
|
|
99
|
-
args: ['script.js'],
|
|
100
|
-
intervalSeconds: 7200,
|
|
101
|
-
});
|
|
102
|
-
// Make launchctl list throw (simulating unloaded state)
|
|
103
|
-
execFileSyncMock.mockImplementation((cmd, args) => {
|
|
104
|
-
if (cmd === 'launchctl' && args?.[0] === 'list')
|
|
105
|
-
throw new Error('not loaded');
|
|
106
|
-
});
|
|
107
|
-
expect(await status('ai.pi.test-job')).toBe('not-found');
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
describe('linux (crontab)', () => {
|
|
111
|
-
beforeEach(() => setPlatform('linux'));
|
|
112
|
-
it('install appends tagged line to crontab', async () => {
|
|
113
|
-
execFileSyncMock.mockReturnValue('');
|
|
114
|
-
const { install } = await import('../scheduler.js');
|
|
115
|
-
await install({
|
|
116
|
-
name: 'ai.pi.test-job',
|
|
117
|
-
command: '/usr/bin/node',
|
|
118
|
-
args: ['/path/to/script.js', '--once'],
|
|
119
|
-
intervalSeconds: 14400, // 4 hours
|
|
120
|
-
});
|
|
121
|
-
// Find the writeCrontab call: execFileSync('crontab', ['-'], { input: ... })
|
|
122
|
-
const writeCall = execFileSyncMock.mock.calls.find((c) => c[0] === 'crontab' && Array.isArray(c[1]) && c[1][0] === '-');
|
|
123
|
-
expect(writeCall).toBeDefined();
|
|
124
|
-
const written = writeCall[2].input;
|
|
125
|
-
expect(written).toContain('# @pi-scheduler:ai.pi.test-job');
|
|
126
|
-
expect(written).toContain("'/usr/bin/node' '/path/to/script.js' '--once'");
|
|
127
|
-
expect(written).toContain('0 */4 * * *');
|
|
128
|
-
});
|
|
129
|
-
it('uninstall removes tagged line from crontab', async () => {
|
|
130
|
-
execFileSyncMock.mockReturnValue('0 */4 * * * /usr/bin/node script.js # @pi-scheduler:ai.pi.test-job\n' +
|
|
131
|
-
'0 * * * * /other/job\n');
|
|
132
|
-
const { uninstall } = await import('../scheduler.js');
|
|
133
|
-
await uninstall('ai.pi.test-job');
|
|
134
|
-
const writeCall = execFileSyncMock.mock.calls.find((c) => c[0] === 'crontab' && Array.isArray(c[1]) && c[1][0] === '-');
|
|
135
|
-
expect(writeCall).toBeDefined();
|
|
136
|
-
const written = writeCall[2].input;
|
|
137
|
-
expect(written).not.toContain('ai.pi.test-job');
|
|
138
|
-
expect(written).toContain('/other/job');
|
|
139
|
-
});
|
|
140
|
-
it('status returns installed when tag exists in crontab', async () => {
|
|
141
|
-
execFileSyncMock.mockReturnValue('0 */4 * * * /usr/bin/node script.js # @pi-scheduler:ai.pi.test-job\n');
|
|
142
|
-
const { status } = await import('../scheduler.js');
|
|
143
|
-
expect(await status('ai.pi.test-job')).toBe('installed');
|
|
144
|
-
});
|
|
145
|
-
it('status returns not-found when no matching tag', async () => {
|
|
146
|
-
execFileSyncMock.mockReturnValue('0 * * * * /other/job\n');
|
|
147
|
-
const { status } = await import('../scheduler.js');
|
|
148
|
-
expect(await status('ai.pi.test-job')).toBe('not-found');
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
describe('win32 (schtasks)', () => {
|
|
152
|
-
beforeEach(() => setPlatform('win32'));
|
|
153
|
-
it('install calls schtasks /create with unquoted args', async () => {
|
|
154
|
-
const { install } = await import('../scheduler.js');
|
|
155
|
-
await install({
|
|
156
|
-
name: 'ai.pi.test-job',
|
|
157
|
-
command: 'node',
|
|
158
|
-
args: ['C:\\path\\script.js'],
|
|
159
|
-
intervalSeconds: 14400, // 240 minutes
|
|
160
|
-
});
|
|
161
|
-
// Verify /tr uses Windows quoting (no single quotes)
|
|
162
|
-
const createCall = execFileSyncMock.mock.calls.find((c) => c[0] === 'schtasks' && Array.isArray(c[1]) && c[1].includes('/create'));
|
|
163
|
-
expect(createCall).toBeDefined();
|
|
164
|
-
const args = createCall[1];
|
|
165
|
-
const trIdx = args.indexOf('/tr');
|
|
166
|
-
expect(trIdx).toBeGreaterThan(-1);
|
|
167
|
-
const trValue = args[trIdx + 1];
|
|
168
|
-
expect(trValue).toBe('node C:\\path\\script.js');
|
|
169
|
-
});
|
|
170
|
-
it('install quotes args with spaces on Windows', async () => {
|
|
171
|
-
const { install } = await import('../scheduler.js');
|
|
172
|
-
await install({
|
|
173
|
-
name: 'ai.pi.space-job',
|
|
174
|
-
command: 'C:\\Program Files\\node.exe',
|
|
175
|
-
args: ['C:\\my scripts\\run.js'],
|
|
176
|
-
intervalSeconds: 3600,
|
|
177
|
-
});
|
|
178
|
-
const createCall = execFileSyncMock.mock.calls.find((c) => c[0] === 'schtasks' && Array.isArray(c[1]) && c[1].includes('/create'));
|
|
179
|
-
const args = createCall[1];
|
|
180
|
-
const trValue = args[args.indexOf('/tr') + 1];
|
|
181
|
-
expect(trValue).toBe('"C:\\Program Files\\node.exe" "C:\\my scripts\\run.js"');
|
|
182
|
-
});
|
|
183
|
-
it('install uses /sc daily for intervals >= 24 hours', async () => {
|
|
184
|
-
const { install } = await import('../scheduler.js');
|
|
185
|
-
await install({
|
|
186
|
-
name: 'ai.pi.daily-job',
|
|
187
|
-
command: 'node',
|
|
188
|
-
args: ['script.js'],
|
|
189
|
-
intervalSeconds: 86400, // 24 hours
|
|
190
|
-
});
|
|
191
|
-
expect(execFileSyncMock).toHaveBeenCalledWith('schtasks', expect.arrayContaining(['/create', '/tn', 'ai.pi.daily-job', '/sc', 'daily', '/mo', '1']), { stdio: 'ignore' });
|
|
192
|
-
});
|
|
193
|
-
it('uninstall calls schtasks /delete', async () => {
|
|
194
|
-
const { uninstall } = await import('../scheduler.js');
|
|
195
|
-
await uninstall('ai.pi.test-job');
|
|
196
|
-
expect(execFileSyncMock).toHaveBeenCalledWith('schtasks', ['/delete', '/tn', 'ai.pi.test-job', '/f'], { stdio: 'ignore' });
|
|
197
|
-
});
|
|
198
|
-
it('status returns installed when schtasks /query succeeds', async () => {
|
|
199
|
-
execFileSyncMock.mockReturnValue('');
|
|
200
|
-
const { status } = await import('../scheduler.js');
|
|
201
|
-
expect(await status('ai.pi.test-job')).toBe('installed');
|
|
202
|
-
});
|
|
203
|
-
it('status returns not-found when schtasks /query throws', async () => {
|
|
204
|
-
execFileSyncMock.mockImplementation(() => {
|
|
205
|
-
throw new Error('task not found');
|
|
206
|
-
});
|
|
207
|
-
const { status } = await import('../scheduler.js');
|
|
208
|
-
expect(await status('ai.pi.test-job')).toBe('not-found');
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
describe('unsupported platform', () => {
|
|
212
|
-
it('install throws on unsupported platform', async () => {
|
|
213
|
-
setPlatform('freebsd');
|
|
214
|
-
const { install } = await import('../scheduler.js');
|
|
215
|
-
await expect(install({ name: 'test', command: 'echo', intervalSeconds: 60 })).rejects.toThrow('Unsupported platform');
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
//# sourceMappingURL=scheduler.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.test.js","sourceRoot":"","sources":["../../src/__tests__/scheduler.test.ts"],"names":[],"mappings":"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"}
|
package/dist/scheduler.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export interface ScheduleJobConfig {
|
|
2
|
-
name: string;
|
|
3
|
-
/** Executable path (e.g. process.execPath). */
|
|
4
|
-
command: string;
|
|
5
|
-
/** Arguments to pass to the command. */
|
|
6
|
-
args?: string[];
|
|
7
|
-
intervalSeconds: number;
|
|
8
|
-
description?: string;
|
|
9
|
-
}
|
|
10
|
-
export type ScheduleStatus = 'installed' | 'not-found';
|
|
11
|
-
export declare function install(config: ScheduleJobConfig): Promise<void>;
|
|
12
|
-
export declare function uninstall(name: string): Promise<void>;
|
|
13
|
-
export declare function status(name: string): Promise<ScheduleStatus>;
|
|
14
|
-
//# sourceMappingURL=scheduler.d.ts.map
|
package/dist/scheduler.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,WAAW,CAAC;AAEvD,wBAAsB,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYtE;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAY3D;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAYlE"}
|
package/dist/scheduler.js
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-platform system scheduled task registration.
|
|
3
|
-
*
|
|
4
|
-
* Supports:
|
|
5
|
-
* - macOS: launchd LaunchAgent (~/Library/LaunchAgents/)
|
|
6
|
-
* - Linux: user crontab (tagged lines)
|
|
7
|
-
* - Windows: Task Scheduler (schtasks)
|
|
8
|
-
*/
|
|
9
|
-
import { execFileSync } from 'node:child_process';
|
|
10
|
-
import { existsSync, mkdirSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
11
|
-
import { homedir } from 'node:os';
|
|
12
|
-
import { join } from 'node:path';
|
|
13
|
-
export async function install(config) {
|
|
14
|
-
const platform = process.platform;
|
|
15
|
-
switch (platform) {
|
|
16
|
-
case 'darwin':
|
|
17
|
-
return installDarwin(config);
|
|
18
|
-
case 'linux':
|
|
19
|
-
return installLinux(config);
|
|
20
|
-
case 'win32':
|
|
21
|
-
return installWin32(config);
|
|
22
|
-
default:
|
|
23
|
-
throw new Error(`Unsupported platform for scheduler: ${platform}`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
export async function uninstall(name) {
|
|
27
|
-
const platform = process.platform;
|
|
28
|
-
switch (platform) {
|
|
29
|
-
case 'darwin':
|
|
30
|
-
return uninstallDarwin(name);
|
|
31
|
-
case 'linux':
|
|
32
|
-
return uninstallLinux(name);
|
|
33
|
-
case 'win32':
|
|
34
|
-
return uninstallWin32(name);
|
|
35
|
-
default:
|
|
36
|
-
throw new Error(`Unsupported platform for scheduler: ${platform}`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
export async function status(name) {
|
|
40
|
-
const platform = process.platform;
|
|
41
|
-
switch (platform) {
|
|
42
|
-
case 'darwin':
|
|
43
|
-
return statusDarwin(name);
|
|
44
|
-
case 'linux':
|
|
45
|
-
return statusLinux(name);
|
|
46
|
-
case 'win32':
|
|
47
|
-
return statusWin32(name);
|
|
48
|
-
default:
|
|
49
|
-
return 'not-found';
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// ─── macOS (launchd) ────────────────────────────────────────────────────────
|
|
53
|
-
function plistPath(name) {
|
|
54
|
-
return join(homedir(), 'Library', 'LaunchAgents', `${name}.plist`);
|
|
55
|
-
}
|
|
56
|
-
function generatePlist(config) {
|
|
57
|
-
const allArgs = [config.command, ...(config.args ?? [])];
|
|
58
|
-
const argsXml = allArgs.map((a) => ` <string>${escapeXml(a)}</string>`).join('\n');
|
|
59
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
60
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
61
|
-
<plist version="1.0">
|
|
62
|
-
<dict>
|
|
63
|
-
<key>Label</key>
|
|
64
|
-
<string>${escapeXml(config.name)}</string>
|
|
65
|
-
<key>ProgramArguments</key>
|
|
66
|
-
<array>
|
|
67
|
-
${argsXml}
|
|
68
|
-
</array>
|
|
69
|
-
<key>StartInterval</key>
|
|
70
|
-
<integer>${config.intervalSeconds}</integer>
|
|
71
|
-
<key>RunAtLoad</key>
|
|
72
|
-
<false/>
|
|
73
|
-
<key>StandardOutPath</key>
|
|
74
|
-
<string>/tmp/${escapeXml(config.name)}.stdout.log</string>
|
|
75
|
-
<key>StandardErrorPath</key>
|
|
76
|
-
<string>/tmp/${escapeXml(config.name)}.stderr.log</string>
|
|
77
|
-
</dict>
|
|
78
|
-
</plist>`;
|
|
79
|
-
}
|
|
80
|
-
function installDarwin(config) {
|
|
81
|
-
const filePath = plistPath(config.name);
|
|
82
|
-
const dir = join(homedir(), 'Library', 'LaunchAgents');
|
|
83
|
-
mkdirSync(dir, { recursive: true });
|
|
84
|
-
// Unload existing if present
|
|
85
|
-
if (existsSync(filePath)) {
|
|
86
|
-
try {
|
|
87
|
-
execFileSync('launchctl', ['unload', filePath], { stdio: 'ignore' });
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
// may not be loaded
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
writeFileSync(filePath, generatePlist(config), 'utf-8');
|
|
94
|
-
execFileSync('launchctl', ['load', '-w', filePath], { stdio: 'ignore' });
|
|
95
|
-
}
|
|
96
|
-
function uninstallDarwin(name) {
|
|
97
|
-
const filePath = plistPath(name);
|
|
98
|
-
if (!existsSync(filePath))
|
|
99
|
-
return;
|
|
100
|
-
try {
|
|
101
|
-
execFileSync('launchctl', ['unload', filePath], { stdio: 'ignore' });
|
|
102
|
-
}
|
|
103
|
-
catch {
|
|
104
|
-
// may not be loaded
|
|
105
|
-
}
|
|
106
|
-
unlinkSync(filePath);
|
|
107
|
-
}
|
|
108
|
-
function statusDarwin(name) {
|
|
109
|
-
const filePath = plistPath(name);
|
|
110
|
-
if (!existsSync(filePath))
|
|
111
|
-
return 'not-found';
|
|
112
|
-
try {
|
|
113
|
-
execFileSync('launchctl', ['list', name], { stdio: 'ignore' });
|
|
114
|
-
return 'installed';
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
// plist exists but not loaded
|
|
118
|
-
return 'not-found';
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
// ─── Linux (crontab) ────────────────────────────────────────────────────────
|
|
122
|
-
const CRON_TAG_PREFIX = '# @pi-scheduler:';
|
|
123
|
-
function intervalToCron(seconds) {
|
|
124
|
-
const minutes = Math.max(1, Math.round(seconds / 60));
|
|
125
|
-
if (minutes < 60)
|
|
126
|
-
return `*/${minutes} * * * *`;
|
|
127
|
-
const hours = Math.round(minutes / 60);
|
|
128
|
-
if (hours < 24)
|
|
129
|
-
return `0 */${hours} * * *`;
|
|
130
|
-
return `0 0 */${Math.round(hours / 24)} * *`;
|
|
131
|
-
}
|
|
132
|
-
function readCrontab() {
|
|
133
|
-
try {
|
|
134
|
-
return execFileSync('crontab', ['-l'], { encoding: 'utf-8' });
|
|
135
|
-
}
|
|
136
|
-
catch {
|
|
137
|
-
return '';
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
function writeCrontab(content) {
|
|
141
|
-
execFileSync('crontab', ['-'], { input: content, stdio: ['pipe', 'ignore', 'inherit'] });
|
|
142
|
-
}
|
|
143
|
-
function installLinux(config) {
|
|
144
|
-
const tag = `${CRON_TAG_PREFIX}${config.name}`;
|
|
145
|
-
const cronExpr = intervalToCron(config.intervalSeconds);
|
|
146
|
-
const fullCommand = buildPosixCommand(config);
|
|
147
|
-
const line = `${cronExpr} ${fullCommand} ${tag}`;
|
|
148
|
-
let current = readCrontab();
|
|
149
|
-
// Remove existing entry for this name
|
|
150
|
-
current = current
|
|
151
|
-
.split('\n')
|
|
152
|
-
.filter((l) => !l.includes(`${CRON_TAG_PREFIX}${config.name}`))
|
|
153
|
-
.join('\n');
|
|
154
|
-
const newContent = `${current.trimEnd()}\n${line}\n`;
|
|
155
|
-
writeCrontab(newContent);
|
|
156
|
-
}
|
|
157
|
-
function uninstallLinux(name) {
|
|
158
|
-
const current = readCrontab();
|
|
159
|
-
const filtered = current
|
|
160
|
-
.split('\n')
|
|
161
|
-
.filter((l) => !l.includes(`${CRON_TAG_PREFIX}${name}`))
|
|
162
|
-
.join('\n');
|
|
163
|
-
writeCrontab(filtered);
|
|
164
|
-
}
|
|
165
|
-
function statusLinux(name) {
|
|
166
|
-
const current = readCrontab();
|
|
167
|
-
return current.includes(`${CRON_TAG_PREFIX}${name}`) ? 'installed' : 'not-found';
|
|
168
|
-
}
|
|
169
|
-
// ─── Windows (Task Scheduler) ───────────────────────────────────────────────
|
|
170
|
-
function installWin32(config) {
|
|
171
|
-
// Delete existing if present
|
|
172
|
-
try {
|
|
173
|
-
execFileSync('schtasks', ['/delete', '/tn', config.name, '/f'], { stdio: 'ignore' });
|
|
174
|
-
}
|
|
175
|
-
catch {
|
|
176
|
-
// task may not exist
|
|
177
|
-
}
|
|
178
|
-
const fullCommand = buildWin32Command(config);
|
|
179
|
-
const minutes = Math.max(1, Math.round(config.intervalSeconds / 60));
|
|
180
|
-
const hours = Math.round(minutes / 60);
|
|
181
|
-
// schtasks /mo limits: minute 1-1439, hourly 1-23, daily 1-365
|
|
182
|
-
let sc;
|
|
183
|
-
let mo;
|
|
184
|
-
if (minutes < 60) {
|
|
185
|
-
sc = 'minute';
|
|
186
|
-
mo = String(minutes);
|
|
187
|
-
}
|
|
188
|
-
else if (hours < 24) {
|
|
189
|
-
sc = 'hourly';
|
|
190
|
-
mo = String(hours);
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
sc = 'daily';
|
|
194
|
-
mo = String(Math.max(1, Math.round(hours / 24)));
|
|
195
|
-
}
|
|
196
|
-
execFileSync('schtasks', ['/create', '/tn', config.name, '/tr', fullCommand, '/sc', sc, '/mo', mo, '/f'], { stdio: 'ignore' });
|
|
197
|
-
}
|
|
198
|
-
function uninstallWin32(name) {
|
|
199
|
-
try {
|
|
200
|
-
execFileSync('schtasks', ['/delete', '/tn', name, '/f'], { stdio: 'ignore' });
|
|
201
|
-
}
|
|
202
|
-
catch {
|
|
203
|
-
// task may not exist
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
function statusWin32(name) {
|
|
207
|
-
try {
|
|
208
|
-
execFileSync('schtasks', ['/query', '/tn', name], { stdio: 'ignore' });
|
|
209
|
-
return 'installed';
|
|
210
|
-
}
|
|
211
|
-
catch {
|
|
212
|
-
return 'not-found';
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
216
|
-
function escapeXml(s) {
|
|
217
|
-
return s
|
|
218
|
-
.replace(/&/g, '&')
|
|
219
|
-
.replace(/</g, '<')
|
|
220
|
-
.replace(/>/g, '>')
|
|
221
|
-
.replace(/"/g, '"');
|
|
222
|
-
}
|
|
223
|
-
function shellEscape(s) {
|
|
224
|
-
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
225
|
-
}
|
|
226
|
-
function buildPosixCommand(config) {
|
|
227
|
-
const parts = [config.command, ...(config.args ?? [])];
|
|
228
|
-
return parts.map(shellEscape).join(' ');
|
|
229
|
-
}
|
|
230
|
-
function buildWin32Command(config) {
|
|
231
|
-
const parts = [config.command, ...(config.args ?? [])];
|
|
232
|
-
// Windows cmd: quote args containing spaces with double quotes
|
|
233
|
-
return parts.map((s) => (/[\s"]/.test(s) ? `"${s.replace(/"/g, '\\"')}"` : s)).join(' ');
|
|
234
|
-
}
|
|
235
|
-
//# sourceMappingURL=scheduler.js.map
|
package/dist/scheduler.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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"}
|