hirify-cli 0.4.7 → 0.5.0
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/README.md +167 -51
- package/bin/hirify.js +3 -1883
- package/bin/lib/api.js +130 -0
- package/bin/lib/auth.js +113 -0
- package/bin/lib/browser.js +34 -0
- package/bin/lib/cli.js +126 -0
- package/bin/lib/commands.js +827 -0
- package/bin/lib/config.js +27 -0
- package/bin/lib/errors.js +20 -0
- package/bin/lib/http.js +113 -0
- package/bin/lib/input.js +39 -0
- package/bin/lib/loopback.js +65 -0
- package/bin/lib/main.js +103 -0
- package/bin/lib/messages.js +62 -0
- package/bin/lib/store.js +118 -0
- package/bin/lib/update.js +171 -0
- package/bin/open-browser.js +2 -13
- package/npm-shrinkwrap.json +349 -0
- package/package.json +17 -4
- package/skills/hirify/SKILL.md +51 -76
- package/skills/hirify/reference.md +20 -13
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { realpathSync, readFileSync, existsSync, mkdirSync, mkdtempSync, renameSync, rmSync, writeFileSync, openSync, fsyncSync, closeSync, lstatSync } from 'node:fs'
|
|
2
|
+
import { join, dirname, resolve, relative, isAbsolute } from 'node:path'
|
|
3
|
+
import { createHash, randomUUID } from 'node:crypto'
|
|
4
|
+
import spawn from 'cross-spawn'
|
|
5
|
+
import semver from 'semver'
|
|
6
|
+
import lockfile from 'proper-lockfile'
|
|
7
|
+
import { CliError, aborted } from './errors.js'
|
|
8
|
+
import { makePrivate } from './store.js'
|
|
9
|
+
import { requireJSON, delay } from './http.js'
|
|
10
|
+
|
|
11
|
+
export const PACKAGE_NAME = 'hirify-cli'
|
|
12
|
+
export function runProcess(command, args, { signal, timeout = 120000, env = process.env, cwd } = {}) {
|
|
13
|
+
aborted(signal)
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
const child = spawn(command, args, { env, cwd, detached: process.platform !== 'win32', windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] })
|
|
16
|
+
let stdout = '', stderr = '', expired = false
|
|
17
|
+
let forceTimer
|
|
18
|
+
const stop = () => {
|
|
19
|
+
if (!child.pid) return
|
|
20
|
+
if (process.platform === 'win32') spawn('taskkill.exe', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' }).on('error', () => child.kill())
|
|
21
|
+
else { try { process.kill(-child.pid, 'SIGTERM') } catch {}; forceTimer = setTimeout(() => { try { process.kill(-child.pid, 'SIGKILL') } catch {} }, 800); forceTimer.unref() }
|
|
22
|
+
}
|
|
23
|
+
const timer = setTimeout(() => { expired = true; stop() }, timeout)
|
|
24
|
+
const cancel = stop
|
|
25
|
+
signal?.addEventListener('abort', cancel, { once: true })
|
|
26
|
+
child.stdout?.on('data', v => { if (stdout.length < 1024 * 1024) stdout += v })
|
|
27
|
+
child.stderr?.on('data', v => { if (stderr.length < 1024 * 1024) stderr += v })
|
|
28
|
+
child.once('error', () => { clearTimeout(timer); signal?.removeEventListener('abort', cancel); reject(new CliError('process_start_failed', 'Could not start the package manager. Check npm on PATH.')) })
|
|
29
|
+
child.once('close', (code, childSignal) => { clearTimeout(timer); clearTimeout(forceTimer); signal?.removeEventListener('abort', cancel); if (signal?.aborted) reject(signal.reason); else if (expired) reject(new CliError('update_timeout', 'The package manager did not finish in time. The active CLI was not replaced.')); else resolve({ code, signal: childSignal, stdout, stderr }) })
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
const real = path => { try { return realpathSync(path) } catch { return resolve(path) } }
|
|
33
|
+
export function updateDirectory(configDir, baseRoot) {
|
|
34
|
+
return join(configDir, 'updates', createHash('sha256').update(real(baseRoot)).digest('hex').slice(0, 24))
|
|
35
|
+
}
|
|
36
|
+
function readJSON(file) { try { return JSON.parse(readFileSync(file, 'utf8')) } catch { return null } }
|
|
37
|
+
async function privateDirectory(path, signal) { mkdirSync(path, { recursive: true, mode: 0o700 }); await makePrivate(path, true, signal) }
|
|
38
|
+
async function atomicJSON(file, value, signal) {
|
|
39
|
+
await privateDirectory(dirname(file), signal)
|
|
40
|
+
const temp = file + '.' + randomUUID() + '.tmp'
|
|
41
|
+
let fd
|
|
42
|
+
try {
|
|
43
|
+
fd = openSync(temp, 'wx', 0o600); writeFileSync(fd, JSON.stringify(value, null, 2) + '\n'); fsyncSync(fd); closeSync(fd); fd = undefined
|
|
44
|
+
if (process.platform === 'win32') await makePrivate(temp, false, signal)
|
|
45
|
+
renameSync(temp, file)
|
|
46
|
+
if (process.platform !== 'win32') { const dir = openSync(dirname(file), 'r'); try { fsyncSync(dir) } finally { closeSync(dir) } }
|
|
47
|
+
} finally { if (fd !== undefined) closeSync(fd); try { rmSync(temp) } catch {} }
|
|
48
|
+
}
|
|
49
|
+
export function activeInstallation(configDir, baseRoot, baseVersion, pin = '') {
|
|
50
|
+
const dir = updateDirectory(configDir, baseRoot)
|
|
51
|
+
const state = readJSON(join(dir, 'active.json'))
|
|
52
|
+
if (!state || state.base_version !== baseVersion || !semver.valid(state.version) || (pin && pin !== state.version)) return null
|
|
53
|
+
if (!state.pinned && !semver.gt(state.version, baseVersion)) return null
|
|
54
|
+
// The pointer contains only a validated version, never an arbitrary executable path.
|
|
55
|
+
const root = join(dir, 'versions', state.version, 'node_modules', PACKAGE_NAME)
|
|
56
|
+
const pkg = readJSON(join(root, 'package.json'))
|
|
57
|
+
if (pkg?.name !== PACKAGE_NAME || pkg.version !== state.version || !semver.satisfies(process.version, pkg.engines?.node || '*') || !existsSync(join(root, 'bin', 'lib', 'main.js'))) return null
|
|
58
|
+
// Selection is read-only, including for offline version. ACLs are set during installation.
|
|
59
|
+
for (const directory of [configDir, join(configDir, 'updates'), dir, join(dir, 'versions'), dirname(dirname(root))]) {
|
|
60
|
+
const stat = lstatSync(directory)
|
|
61
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || (process.platform !== 'win32' && (stat.uid !== process.getuid() || (stat.mode & 0o022)))) throw new CliError('unsafe_storage', 'The managed CLI directory must be private and owned by this user.')
|
|
62
|
+
}
|
|
63
|
+
const canonical = real(root)
|
|
64
|
+
if (relative(real(dir), canonical).startsWith('..') || isAbsolute(relative(real(dir), canonical)) || lstatSync(root).isSymbolicLink()) return null
|
|
65
|
+
return { root, version: state.version, pinned: Boolean(state.pinned), previous: state.previous || null }
|
|
66
|
+
}
|
|
67
|
+
export function createUpdater({ config, http, signal, output, event, packageRoot, baseRoot = packageRoot, baseVersion = config.version, run = runProcess }) {
|
|
68
|
+
const dir = updateDirectory(config.dir, baseRoot)
|
|
69
|
+
const stateFile = join(dir, 'active.json')
|
|
70
|
+
async function installation() {
|
|
71
|
+
// A checkout or a local/npx dependency is never modified or auto-managed.
|
|
72
|
+
const canonical = real(baseRoot)
|
|
73
|
+
if (!canonical.includes('node_modules') || config.env.npm_command === 'exec' || config.env.npm_lifecycle_event === 'npx') return { owner: 'unmanaged', reason: 'checkout_or_ephemeral' }
|
|
74
|
+
try {
|
|
75
|
+
const answer = await run('npm', ['root', '--global'], { signal, timeout: 3000 })
|
|
76
|
+
if (answer.code !== 0) return { owner: 'unknown', reason: 'npm_root_failed' }
|
|
77
|
+
return real(join(answer.stdout.trim(), PACKAGE_NAME)) === canonical ? { owner: 'npm-global', reason: 'verified' } : { owner: 'unmanaged', reason: 'different_prefix' }
|
|
78
|
+
} catch (error) { if (signal?.aborted) throw error; return { owner: 'unknown', reason: error.code || 'npm_unavailable' } }
|
|
79
|
+
}
|
|
80
|
+
async function registry() {
|
|
81
|
+
const answer = await run('npm', ['config', 'get', 'registry'], { signal, timeout: 3000 })
|
|
82
|
+
if (answer.code !== 0) throw new CliError('update_registry', 'Could not determine the npm registry.')
|
|
83
|
+
let url
|
|
84
|
+
try { url = new URL(answer.stdout.trim()) } catch { throw new CliError('update_registry', 'The npm registry URL is invalid.') }
|
|
85
|
+
if (url.protocol !== 'https:' || url.username || url.password || url.search || url.hash) throw new CliError('update_registry', 'Use an HTTPS npm registry without credentials in its URL.')
|
|
86
|
+
return url.href.replace(/\/$/, '')
|
|
87
|
+
}
|
|
88
|
+
async function check(version = 'latest') {
|
|
89
|
+
if (version !== 'latest' && !semver.valid(version)) throw new CliError('invalid_arguments', 'Use an exact semantic version, such as hirify update 0.5.0.')
|
|
90
|
+
const registryURL = await registry()
|
|
91
|
+
const res = await http.request(`${registryURL}/${PACKAGE_NAME}/${encodeURIComponent(version)}`, { safe: true, timeout: 3000 })
|
|
92
|
+
if (!res.ok) throw new CliError('update_check_failed', 'Could not check the requested CLI version.', { status: res.status })
|
|
93
|
+
const pkg = requireJSON(res)
|
|
94
|
+
if (pkg.name !== PACKAGE_NAME || !semver.valid(pkg.version) || (version !== 'latest' && pkg.version !== version) || !pkg.dist?.integrity || !semver.satisfies(process.version, pkg.engines?.node || '*')) throw new CliError('update_incompatible', 'The requested CLI release is invalid or does not support this Node version.')
|
|
95
|
+
return { version: pkg.version, registry: registryURL, integrity: pkg.dist.integrity, available: semver.gt(pkg.version, config.version) }
|
|
96
|
+
}
|
|
97
|
+
async function install(target, { pin = false } = {}) {
|
|
98
|
+
const owner = await installation()
|
|
99
|
+
if (owner.owner !== 'npm-global') throw new CliError('update_owner_unknown', 'This installation is managed elsewhere. Update it with the package manager that installed it, or run npx hirify-cli@<version>.')
|
|
100
|
+
await privateDirectory(config.dir, signal); await privateDirectory(dir, signal); await privateDirectory(join(dir, 'versions'), signal)
|
|
101
|
+
let release
|
|
102
|
+
while (!release) {
|
|
103
|
+
aborted(signal)
|
|
104
|
+
try { release = await lockfile.lock(stateFile, { realpath: false, stale: 600000, update: 10000 }) }
|
|
105
|
+
catch (error) { if (error.code !== 'ELOCKED') throw new CliError('update_lock_failed', 'Could not lock the update directory.'); await delay(100, signal) }
|
|
106
|
+
}
|
|
107
|
+
let staging
|
|
108
|
+
try {
|
|
109
|
+
const previousState = readJSON(stateFile)
|
|
110
|
+
const destination = join(dir, 'versions', target.version)
|
|
111
|
+
if (!existsSync(destination)) {
|
|
112
|
+
// npm misidentifies its root when --prefix contains an ancestor symlink (macOS /var).
|
|
113
|
+
staging = realpathSync(mkdtempSync(join(dir, '.staging-'))); await makePrivate(staging, true, signal)
|
|
114
|
+
const result = await run('npm', ['install', '--prefix', staging, '--global=false', '--save=true', '--package-lock=true', '--ignore-scripts', '--no-audit', '--no-fund', '--strict-ssl=true', '--registry', target.registry, `${PACKAGE_NAME}@${target.version}`], { signal, timeout: 180000, env: { ...config.env, HIRIFY_NO_AUTO_UPDATE: '1' } })
|
|
115
|
+
if (result.code !== 0) throw new CliError('update_install_failed', 'The update could not be installed. The active CLI was not replaced.')
|
|
116
|
+
const pkgPath = join(staging, 'node_modules', PACKAGE_NAME)
|
|
117
|
+
const pkg = readJSON(join(pkgPath, 'package.json'))
|
|
118
|
+
const lock = readJSON(join(staging, 'package-lock.json'))
|
|
119
|
+
if (pkg?.name !== PACKAGE_NAME || pkg.version !== target.version || !existsSync(join(pkgPath, 'bin', 'lib', 'main.js')) || lock?.packages?.[`node_modules/${PACKAGE_NAME}`]?.integrity !== target.integrity) throw new CliError('update_verification_failed', 'The installed package did not match the selected release. The active CLI was not replaced.')
|
|
120
|
+
const verify = await run(process.execPath, [join(pkgPath, 'bin', 'hirify.js'), 'version'], { signal, timeout: 10000, env: { ...config.env, HIRIFY_NO_AUTO_UPDATE: '1', HIRIFY_INTERNAL_REEXEC: '1' } })
|
|
121
|
+
if (verify.code !== 0 || verify.stdout.trim() !== target.version) throw new CliError('update_verification_failed', 'The new CLI could not start. The active CLI was not replaced.')
|
|
122
|
+
renameSync(staging, destination); staging = null
|
|
123
|
+
}
|
|
124
|
+
const cachedRoot = join(destination, 'node_modules', PACKAGE_NAME)
|
|
125
|
+
const cachedPackage = readJSON(join(cachedRoot, 'package.json'))
|
|
126
|
+
const cachedLock = readJSON(join(destination, 'package-lock.json'))
|
|
127
|
+
if (cachedPackage?.name !== PACKAGE_NAME || cachedPackage.version !== target.version || !semver.satisfies(process.version, cachedPackage.engines?.node || '*') || !existsSync(join(cachedRoot, 'bin', 'lib', 'main.js')) || cachedLock?.packages?.[`node_modules/${PACKAGE_NAME}`]?.integrity !== target.integrity) throw new CliError('update_verification_failed', 'The cached artifact does not match the selected release. The active CLI was not replaced.')
|
|
128
|
+
aborted(signal)
|
|
129
|
+
const previous = previousState?.base_version === baseVersion ? (previousState.version === target.version ? previousState.previous : previousState.version) : baseVersion
|
|
130
|
+
const pinned = pin || Boolean(previousState?.version === target.version && previousState.pinned)
|
|
131
|
+
await atomicJSON(stateFile, { schema_version: 1, base_version: baseVersion, version: target.version, integrity: target.integrity, pinned, previous: previous || baseVersion }, signal)
|
|
132
|
+
return { version: target.version, previous: previous || baseVersion, pinned }
|
|
133
|
+
} finally { if (staging) rmSync(staging, { recursive: true, force: true }); await release().catch(() => {}) }
|
|
134
|
+
}
|
|
135
|
+
async function rollback() {
|
|
136
|
+
const state = readJSON(stateFile)
|
|
137
|
+
if (!state || state.base_version !== baseVersion || !semver.valid(state.previous)) throw new CliError('update_no_previous', 'No previous managed CLI version is available. Install an exact package version with npm instead.')
|
|
138
|
+
if (state.previous !== baseVersion && !existsSync(join(dir, 'versions', state.previous, 'node_modules', PACKAGE_NAME, 'bin', 'lib', 'main.js'))) throw new CliError('update_no_previous', 'The previous CLI artifact is unavailable. Install its exact package version with npm instead.')
|
|
139
|
+
let release
|
|
140
|
+
while (!release) {
|
|
141
|
+
aborted(signal)
|
|
142
|
+
try { release = await lockfile.lock(stateFile, { realpath: false, stale: 600000, update: 10000 }) }
|
|
143
|
+
catch (error) { if (error.code !== 'ELOCKED') throw new CliError('update_lock_failed', 'Could not lock the update directory.'); await delay(100, signal) }
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const current = readJSON(stateFile)
|
|
147
|
+
if (current?.version !== state.version) throw new CliError('update_changed', 'Another process changed the active version. Check hirify version before retrying.')
|
|
148
|
+
await atomicJSON(stateFile, { ...state, version: state.previous, previous: state.version, integrity: null, pinned: true }, signal)
|
|
149
|
+
return { version: state.previous, previous: state.version, pinned: true }
|
|
150
|
+
} finally { await release().catch(() => {}) }
|
|
151
|
+
}
|
|
152
|
+
async function automatic() {
|
|
153
|
+
if (config.env.HIRIFY_NO_AUTO_UPDATE === '1' || config.env.HIRIFY_INTERNAL_REEXEC === '1' || config.env.HIRIFY_VERSION_PIN || readJSON(stateFile)?.pinned) return null
|
|
154
|
+
const owner = await installation()
|
|
155
|
+
if (owner.owner !== 'npm-global') { event('update', { code: owner.reason }); return null }
|
|
156
|
+
try {
|
|
157
|
+
const target = await check()
|
|
158
|
+
if (!target.available) { event('update', { code: 'up_to_date' }); return null }
|
|
159
|
+
output.progress(`Installing Hirify CLI ${target.version} in a separate directory...`)
|
|
160
|
+
const result = await install(target)
|
|
161
|
+
output.progress(`Hirify CLI ${result.version} is ready.`)
|
|
162
|
+
return activeInstallation(config.dir, baseRoot, baseVersion)
|
|
163
|
+
} catch (error) {
|
|
164
|
+
if (signal?.aborted) throw error
|
|
165
|
+
event('update', { code: error.code })
|
|
166
|
+
output.progress(`Update check or installation did not complete (${error.code || 'update_failed'}). Continuing with ${config.version}. Run hirify update --check for details.`)
|
|
167
|
+
return null
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return { installation, check, install, rollback, automatic, dir }
|
|
171
|
+
}
|
package/bin/open-browser.js
CHANGED
|
@@ -1,13 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Windows must not receive the URL through cmd.exe: `&` is command syntax there, so an
|
|
5
|
-
* OAuth URL would be cut off after its first query parameter. Explorer receives the URL
|
|
6
|
-
* as one process argument and leaves every parameter intact.
|
|
7
|
-
*/
|
|
8
|
-
export function browserCandidates(url, platform = process.platform, browser = process.env.BROWSER) {
|
|
9
|
-
if (browser) return [[browser, [url]]]
|
|
10
|
-
if (platform === 'darwin') return [['open', [url]]]
|
|
11
|
-
if (platform === 'win32') return [['explorer.exe', [url]]]
|
|
12
|
-
return [['xdg-open', [url]], ['gio', ['open', url]], ['sensible-browser', [url]], ['x-www-browser', [url]]]
|
|
13
|
-
}
|
|
1
|
+
// Compatibility export for consumers of the browser adapter.
|
|
2
|
+
export { canOpenBrowser, openBrowser } from './lib/browser.js'
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hirify-cli",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"lockfileVersion": 3,
|
|
5
|
+
"requires": true,
|
|
6
|
+
"packages": {
|
|
7
|
+
"": {
|
|
8
|
+
"name": "hirify-cli",
|
|
9
|
+
"version": "0.5.0",
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"cross-spawn": "7.0.6",
|
|
13
|
+
"http-proxy-agent": "7.0.2",
|
|
14
|
+
"https-proxy-agent": "7.0.6",
|
|
15
|
+
"open": "10.2.0",
|
|
16
|
+
"proper-lockfile": "4.1.2",
|
|
17
|
+
"proxy-from-env": "1.1.0",
|
|
18
|
+
"semver": "7.8.5"
|
|
19
|
+
},
|
|
20
|
+
"bin": {
|
|
21
|
+
"hirify": "bin/hirify.js"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"node_modules/agent-base": {
|
|
28
|
+
"version": "7.1.4",
|
|
29
|
+
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
|
30
|
+
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">= 14"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"node_modules/bundle-name": {
|
|
37
|
+
"version": "4.1.0",
|
|
38
|
+
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
|
|
39
|
+
"integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"run-applescript": "^7.0.0"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18"
|
|
46
|
+
},
|
|
47
|
+
"funding": {
|
|
48
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"node_modules/cross-spawn": {
|
|
52
|
+
"version": "7.0.6",
|
|
53
|
+
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
|
54
|
+
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"path-key": "^3.1.0",
|
|
58
|
+
"shebang-command": "^2.0.0",
|
|
59
|
+
"which": "^2.0.1"
|
|
60
|
+
},
|
|
61
|
+
"engines": {
|
|
62
|
+
"node": ">= 8"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"node_modules/debug": {
|
|
66
|
+
"version": "4.4.3",
|
|
67
|
+
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
|
68
|
+
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
|
69
|
+
"license": "MIT",
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"ms": "^2.1.3"
|
|
72
|
+
},
|
|
73
|
+
"engines": {
|
|
74
|
+
"node": ">=6.0"
|
|
75
|
+
},
|
|
76
|
+
"peerDependenciesMeta": {
|
|
77
|
+
"supports-color": {
|
|
78
|
+
"optional": true
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"node_modules/default-browser": {
|
|
83
|
+
"version": "5.5.1",
|
|
84
|
+
"resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.1.tgz",
|
|
85
|
+
"integrity": "sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==",
|
|
86
|
+
"license": "MIT",
|
|
87
|
+
"dependencies": {
|
|
88
|
+
"bundle-name": "^4.1.0",
|
|
89
|
+
"default-browser-id": "^5.0.0"
|
|
90
|
+
},
|
|
91
|
+
"engines": {
|
|
92
|
+
"node": ">=18"
|
|
93
|
+
},
|
|
94
|
+
"funding": {
|
|
95
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"node_modules/default-browser-id": {
|
|
99
|
+
"version": "5.0.1",
|
|
100
|
+
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz",
|
|
101
|
+
"integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==",
|
|
102
|
+
"license": "MIT",
|
|
103
|
+
"engines": {
|
|
104
|
+
"node": ">=18"
|
|
105
|
+
},
|
|
106
|
+
"funding": {
|
|
107
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"node_modules/define-lazy-prop": {
|
|
111
|
+
"version": "3.0.0",
|
|
112
|
+
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
|
|
113
|
+
"integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
|
|
114
|
+
"license": "MIT",
|
|
115
|
+
"engines": {
|
|
116
|
+
"node": ">=12"
|
|
117
|
+
},
|
|
118
|
+
"funding": {
|
|
119
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"node_modules/graceful-fs": {
|
|
123
|
+
"version": "4.2.11",
|
|
124
|
+
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
|
125
|
+
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
|
126
|
+
"license": "ISC"
|
|
127
|
+
},
|
|
128
|
+
"node_modules/http-proxy-agent": {
|
|
129
|
+
"version": "7.0.2",
|
|
130
|
+
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
|
131
|
+
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
|
132
|
+
"license": "MIT",
|
|
133
|
+
"dependencies": {
|
|
134
|
+
"agent-base": "^7.1.0",
|
|
135
|
+
"debug": "^4.3.4"
|
|
136
|
+
},
|
|
137
|
+
"engines": {
|
|
138
|
+
"node": ">= 14"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"node_modules/https-proxy-agent": {
|
|
142
|
+
"version": "7.0.6",
|
|
143
|
+
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
|
144
|
+
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
|
145
|
+
"license": "MIT",
|
|
146
|
+
"dependencies": {
|
|
147
|
+
"agent-base": "^7.1.2",
|
|
148
|
+
"debug": "4"
|
|
149
|
+
},
|
|
150
|
+
"engines": {
|
|
151
|
+
"node": ">= 14"
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"node_modules/is-docker": {
|
|
155
|
+
"version": "3.0.0",
|
|
156
|
+
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
|
|
157
|
+
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
|
|
158
|
+
"license": "MIT",
|
|
159
|
+
"bin": {
|
|
160
|
+
"is-docker": "cli.js"
|
|
161
|
+
},
|
|
162
|
+
"engines": {
|
|
163
|
+
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
164
|
+
},
|
|
165
|
+
"funding": {
|
|
166
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"node_modules/is-inside-container": {
|
|
170
|
+
"version": "1.0.0",
|
|
171
|
+
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
|
|
172
|
+
"integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
|
|
173
|
+
"license": "MIT",
|
|
174
|
+
"dependencies": {
|
|
175
|
+
"is-docker": "^3.0.0"
|
|
176
|
+
},
|
|
177
|
+
"bin": {
|
|
178
|
+
"is-inside-container": "cli.js"
|
|
179
|
+
},
|
|
180
|
+
"engines": {
|
|
181
|
+
"node": ">=14.16"
|
|
182
|
+
},
|
|
183
|
+
"funding": {
|
|
184
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"node_modules/is-wsl": {
|
|
188
|
+
"version": "3.1.1",
|
|
189
|
+
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",
|
|
190
|
+
"integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==",
|
|
191
|
+
"license": "MIT",
|
|
192
|
+
"dependencies": {
|
|
193
|
+
"is-inside-container": "^1.0.0"
|
|
194
|
+
},
|
|
195
|
+
"engines": {
|
|
196
|
+
"node": ">=16"
|
|
197
|
+
},
|
|
198
|
+
"funding": {
|
|
199
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"node_modules/isexe": {
|
|
203
|
+
"version": "2.0.0",
|
|
204
|
+
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
|
205
|
+
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
|
206
|
+
"license": "ISC"
|
|
207
|
+
},
|
|
208
|
+
"node_modules/ms": {
|
|
209
|
+
"version": "2.1.3",
|
|
210
|
+
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
|
211
|
+
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
|
212
|
+
"license": "MIT"
|
|
213
|
+
},
|
|
214
|
+
"node_modules/open": {
|
|
215
|
+
"version": "10.2.0",
|
|
216
|
+
"resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz",
|
|
217
|
+
"integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==",
|
|
218
|
+
"license": "MIT",
|
|
219
|
+
"dependencies": {
|
|
220
|
+
"default-browser": "^5.2.1",
|
|
221
|
+
"define-lazy-prop": "^3.0.0",
|
|
222
|
+
"is-inside-container": "^1.0.0",
|
|
223
|
+
"wsl-utils": "^0.1.0"
|
|
224
|
+
},
|
|
225
|
+
"engines": {
|
|
226
|
+
"node": ">=18"
|
|
227
|
+
},
|
|
228
|
+
"funding": {
|
|
229
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"node_modules/path-key": {
|
|
233
|
+
"version": "3.1.1",
|
|
234
|
+
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
|
235
|
+
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
|
236
|
+
"license": "MIT",
|
|
237
|
+
"engines": {
|
|
238
|
+
"node": ">=8"
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
"node_modules/proper-lockfile": {
|
|
242
|
+
"version": "4.1.2",
|
|
243
|
+
"resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz",
|
|
244
|
+
"integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==",
|
|
245
|
+
"license": "MIT",
|
|
246
|
+
"dependencies": {
|
|
247
|
+
"graceful-fs": "^4.2.4",
|
|
248
|
+
"retry": "^0.12.0",
|
|
249
|
+
"signal-exit": "^3.0.2"
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
"node_modules/proxy-from-env": {
|
|
253
|
+
"version": "1.1.0",
|
|
254
|
+
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
|
255
|
+
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
|
256
|
+
"license": "MIT"
|
|
257
|
+
},
|
|
258
|
+
"node_modules/retry": {
|
|
259
|
+
"version": "0.12.0",
|
|
260
|
+
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
|
261
|
+
"integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
|
|
262
|
+
"license": "MIT",
|
|
263
|
+
"engines": {
|
|
264
|
+
"node": ">= 4"
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
"node_modules/run-applescript": {
|
|
268
|
+
"version": "7.1.0",
|
|
269
|
+
"resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz",
|
|
270
|
+
"integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==",
|
|
271
|
+
"license": "MIT",
|
|
272
|
+
"engines": {
|
|
273
|
+
"node": ">=18"
|
|
274
|
+
},
|
|
275
|
+
"funding": {
|
|
276
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
"node_modules/semver": {
|
|
280
|
+
"version": "7.8.5",
|
|
281
|
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
|
282
|
+
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
|
283
|
+
"license": "ISC",
|
|
284
|
+
"bin": {
|
|
285
|
+
"semver": "bin/semver.js"
|
|
286
|
+
},
|
|
287
|
+
"engines": {
|
|
288
|
+
"node": ">=10"
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
"node_modules/shebang-command": {
|
|
292
|
+
"version": "2.0.0",
|
|
293
|
+
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
|
294
|
+
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
|
295
|
+
"license": "MIT",
|
|
296
|
+
"dependencies": {
|
|
297
|
+
"shebang-regex": "^3.0.0"
|
|
298
|
+
},
|
|
299
|
+
"engines": {
|
|
300
|
+
"node": ">=8"
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
"node_modules/shebang-regex": {
|
|
304
|
+
"version": "3.0.0",
|
|
305
|
+
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
|
306
|
+
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
|
307
|
+
"license": "MIT",
|
|
308
|
+
"engines": {
|
|
309
|
+
"node": ">=8"
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
"node_modules/signal-exit": {
|
|
313
|
+
"version": "3.0.7",
|
|
314
|
+
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
|
315
|
+
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
|
316
|
+
"license": "ISC"
|
|
317
|
+
},
|
|
318
|
+
"node_modules/which": {
|
|
319
|
+
"version": "2.0.2",
|
|
320
|
+
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
321
|
+
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
|
322
|
+
"license": "ISC",
|
|
323
|
+
"dependencies": {
|
|
324
|
+
"isexe": "^2.0.0"
|
|
325
|
+
},
|
|
326
|
+
"bin": {
|
|
327
|
+
"node-which": "bin/node-which"
|
|
328
|
+
},
|
|
329
|
+
"engines": {
|
|
330
|
+
"node": ">= 8"
|
|
331
|
+
}
|
|
332
|
+
},
|
|
333
|
+
"node_modules/wsl-utils": {
|
|
334
|
+
"version": "0.1.0",
|
|
335
|
+
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz",
|
|
336
|
+
"integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==",
|
|
337
|
+
"license": "MIT",
|
|
338
|
+
"dependencies": {
|
|
339
|
+
"is-wsl": "^3.1.0"
|
|
340
|
+
},
|
|
341
|
+
"engines": {
|
|
342
|
+
"node": ">=18"
|
|
343
|
+
},
|
|
344
|
+
"funding": {
|
|
345
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hirify-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Hirify CLI for AI agents: browser sign-in, job feeds, search, reading a vacancy in full, contacts to apply to, and applying on Hirify.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"hirify": "bin/hirify.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
-
"test": "node scripts/test.mjs",
|
|
10
|
-
"
|
|
9
|
+
"test": "node --test scripts/test.mjs scripts/runtime.test.mjs scripts/network.test.mjs scripts/update.test.mjs scripts/storage.test.mjs",
|
|
10
|
+
"build": "node scripts/build.mjs",
|
|
11
|
+
"test:package": "node scripts/verify-package.mjs",
|
|
12
|
+
"prepublishOnly": "node scripts/prepublish-check.mjs",
|
|
13
|
+
"test:install": "node scripts/install-update-smoke.mjs"
|
|
11
14
|
},
|
|
12
15
|
"type": "module",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"cross-spawn": "7.0.6",
|
|
18
|
+
"http-proxy-agent": "7.0.2",
|
|
19
|
+
"https-proxy-agent": "7.0.6",
|
|
20
|
+
"open": "10.2.0",
|
|
21
|
+
"proper-lockfile": "4.1.2",
|
|
22
|
+
"proxy-from-env": "1.1.0",
|
|
23
|
+
"semver": "7.8.5"
|
|
24
|
+
},
|
|
13
25
|
"engines": {
|
|
14
26
|
"node": ">=18"
|
|
15
27
|
},
|
|
@@ -17,7 +29,8 @@
|
|
|
17
29
|
"bin",
|
|
18
30
|
"skills",
|
|
19
31
|
"README.md",
|
|
20
|
-
"NOTICE"
|
|
32
|
+
"NOTICE",
|
|
33
|
+
"npm-shrinkwrap.json"
|
|
21
34
|
],
|
|
22
35
|
"keywords": [
|
|
23
36
|
"hirify",
|