humanenv 0.1.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 +303 -0
- package/package.json +38 -0
- package/packages/cli/package.json +15 -0
- package/packages/cli/src/bin.js +228 -0
- package/packages/client/bin.js +174 -0
- package/packages/client/build.js +57 -0
- package/packages/client/dist/cli.js +1041 -0
- package/packages/client/dist/index.cjs +333 -0
- package/packages/client/dist/index.mjs +296 -0
- package/packages/client/package.json +24 -0
- package/packages/client/src/cli/bin.js +228 -0
- package/packages/client/src/cli/entry.js +465 -0
- package/packages/client/src/index.ts +31 -0
- package/packages/client/src/shared/buffer-shim.d.ts +4 -0
- package/packages/client/src/shared/crypto.ts +98 -0
- package/packages/client/src/shared/errors.ts +32 -0
- package/packages/client/src/shared/index.ts +3 -0
- package/packages/client/src/shared/types.ts +118 -0
- package/packages/client/src/ws-manager.ts +263 -0
- package/packages/server/package.json +21 -0
- package/packages/server/src/auth.ts +13 -0
- package/packages/server/src/db/index.ts +19 -0
- package/packages/server/src/db/interface.ts +33 -0
- package/packages/server/src/db/mongo.ts +166 -0
- package/packages/server/src/db/sqlite.ts +180 -0
- package/packages/server/src/index.ts +123 -0
- package/packages/server/src/pk-manager.ts +79 -0
- package/packages/server/src/routes/index.ts +110 -0
- package/packages/server/src/views/index.ejs +359 -0
- package/packages/server/src/ws/router.ts +263 -0
- package/packages/shared/package.json +13 -0
- package/packages/shared/src/buffer-shim.d.ts +4 -0
- package/packages/shared/src/crypto.ts +98 -0
- package/packages/shared/src/errors.ts +32 -0
- package/packages/shared/src/index.ts +3 -0
- package/packages/shared/src/types.ts +119 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// humanenv CLI - single entry point, works after both npm link and npm publish.
|
|
4
|
+
// Dependencies are bundled via dist/* or resolved from local src/ during development.
|
|
5
|
+
|
|
6
|
+
const path = require('path')
|
|
7
|
+
const fs = require('fs')
|
|
8
|
+
const os = require('os')
|
|
9
|
+
|
|
10
|
+
// ============================================================
|
|
11
|
+
// Resolve module loading strategy
|
|
12
|
+
// ============================================================
|
|
13
|
+
|
|
14
|
+
function loadModule(name) {
|
|
15
|
+
// Try direct require (compiled / node_modules)
|
|
16
|
+
try { return require(name) } catch {}
|
|
17
|
+
// Try relative (workspace source)
|
|
18
|
+
try { return require('./' + name) } catch {}
|
|
19
|
+
// Try local dist
|
|
20
|
+
try { return require('./dist/' + name) } catch {}
|
|
21
|
+
throw new Error(`Cannot find module: ${name}`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { HumanEnvClient } = loadModule('ws-manager.js') || loadModule('client/ws-manager.js') || loadModule('./client/ws-manager.js')
|
|
25
|
+
const { Command } = loadModule('commander')
|
|
26
|
+
const { SKILL_CONTENT } = loadModule('shared/index.js') || loadModule('shared/index.ts') || {}
|
|
27
|
+
|
|
28
|
+
const CREDENTIALS_DIR = path.join(os.homedir(), '.humanenv')
|
|
29
|
+
|
|
30
|
+
function ensureCredentialsDir() {
|
|
31
|
+
if (!fs.existsSync(CREDENTIALS_DIR)) fs.mkdirSync(CREDENTIALS_DIR, { recursive: true })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readCredentials() {
|
|
35
|
+
const p = path.join(CREDENTIALS_DIR, 'credentials.json')
|
|
36
|
+
if (!fs.existsSync(p)) return null
|
|
37
|
+
try { return JSON.parse(fs.readFileSync(p, 'utf8')) } catch { return null }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function writeCredentials(data) {
|
|
41
|
+
ensureCredentialsDir()
|
|
42
|
+
fs.writeFileSync(path.join(CREDENTIALS_DIR, 'credentials.json'), JSON.stringify(data, null, 2), 'utf8')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function ensureSkillFile() {
|
|
46
|
+
const skillPath = path.join(process.cwd(), '.agents', 'skills', 'humanenv-usage', 'SKILL.md')
|
|
47
|
+
if (!fs.existsSync(skillPath)) {
|
|
48
|
+
fs.mkdirSync(path.dirname(skillPath), { recursive: true })
|
|
49
|
+
fs.writeFileSync(skillPath, SKILL_CONTENT || 'HumanEnv skill placeholder', 'utf8')
|
|
50
|
+
if (process.stdout.isTTY) console.log('Generated .agents/skills/humanenv-usage/SKILL.md')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ============================================================
|
|
55
|
+
// CLI
|
|
56
|
+
// ============================================================
|
|
57
|
+
|
|
58
|
+
const { createCommand } = require('commander')
|
|
59
|
+
const program = createCommand()
|
|
60
|
+
|
|
61
|
+
program
|
|
62
|
+
.action(() => {
|
|
63
|
+
ensureSkillFile()
|
|
64
|
+
if (!process.stdout.isTTY) {
|
|
65
|
+
const skillPath = path.join(process.cwd(), '.agents', 'skills', 'humanenv-usage', 'SKILL.md')
|
|
66
|
+
console.log(fs.readFileSync(skillPath, 'utf8'))
|
|
67
|
+
} else {
|
|
68
|
+
console.log('HumanEnv - Secure environment variable injection')
|
|
69
|
+
console.log('')
|
|
70
|
+
console.log('Usage:')
|
|
71
|
+
console.log(' humanenv auth --project-name <name> --server-url <url> [--api-key <key>]')
|
|
72
|
+
console.log(' humanenv auth --project-name <name> --server-url <url> --generate-api-key')
|
|
73
|
+
console.log(' humanenv get <key>')
|
|
74
|
+
console.log(' humanenv set <key> <value>')
|
|
75
|
+
console.log(' humanenv server [--port 3056] [--basicAuth]')
|
|
76
|
+
console.log('')
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
program
|
|
81
|
+
.command('auth')
|
|
82
|
+
.option('--project-name <name>')
|
|
83
|
+
.option('--server-url <url>')
|
|
84
|
+
.option('--api-key <key>')
|
|
85
|
+
.option('--generate-api-key', false)
|
|
86
|
+
.action(async (opts) => {
|
|
87
|
+
ensureSkillFile()
|
|
88
|
+
if (!opts.projectName || !opts.serverUrl) {
|
|
89
|
+
console.error('Error: --project-name and --server-url required')
|
|
90
|
+
process.exit(1)
|
|
91
|
+
}
|
|
92
|
+
const creds = { projectName: opts.projectName, serverUrl: opts.serverUrl, apiKey: opts.apiKey || undefined }
|
|
93
|
+
writeCredentials(creds)
|
|
94
|
+
if (opts.generateApiKey) {
|
|
95
|
+
console.log('API key generation request sent. Admin must approve in dashboard.')
|
|
96
|
+
} else {
|
|
97
|
+
try {
|
|
98
|
+
const client = new HumanEnvClient({ serverUrl: opts.serverUrl, projectName: opts.projectName, projectApiKey: opts.apiKey || '', maxRetries: 3 })
|
|
99
|
+
await client.connect()
|
|
100
|
+
console.log('Authenticated successfully.')
|
|
101
|
+
client.disconnect()
|
|
102
|
+
} catch (e) {
|
|
103
|
+
console.error('Auth failed:', e.message)
|
|
104
|
+
process.exit(1)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
console.log('Credentials stored in', path.join(CREDENTIALS_DIR, 'credentials.json'))
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
program
|
|
111
|
+
.command('get')
|
|
112
|
+
.argument('<key>', 'Environment variable key')
|
|
113
|
+
.action(async (key) => {
|
|
114
|
+
const creds = readCredentials()
|
|
115
|
+
if (!creds) {
|
|
116
|
+
console.error('Error: Not authenticated. Run: humanenv auth --project-name <name> --server-url <url>')
|
|
117
|
+
process.exit(1)
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const client = new HumanEnvClient({ serverUrl: creds.serverUrl, projectName: creds.projectName, projectApiKey: creds.apiKey || '', maxRetries: 3 })
|
|
121
|
+
await client.connect()
|
|
122
|
+
const value = await client.get(key)
|
|
123
|
+
if (!process.stdout.isTTY) process.stdout.write(value)
|
|
124
|
+
else console.log(value)
|
|
125
|
+
client.disconnect()
|
|
126
|
+
} catch (e) {
|
|
127
|
+
console.error('Failed to get env:', e.message)
|
|
128
|
+
process.exit(1)
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
program
|
|
133
|
+
.command('set')
|
|
134
|
+
.argument('<key>', 'Environment variable key')
|
|
135
|
+
.argument('<value>', 'Environment variable value')
|
|
136
|
+
.action(async (key, value) => {
|
|
137
|
+
const creds = readCredentials()
|
|
138
|
+
if (!creds) {
|
|
139
|
+
console.error('Error: Not authenticated. Run: humanenv auth --project-name <name> --server-url <url>')
|
|
140
|
+
process.exit(1)
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const client = new HumanEnvClient({ serverUrl: creds.serverUrl, projectName: creds.projectName, projectApiKey: creds.apiKey || '', maxRetries: 3 })
|
|
144
|
+
await client.connect()
|
|
145
|
+
await client.set(key, value)
|
|
146
|
+
console.log('Set', key)
|
|
147
|
+
client.disconnect()
|
|
148
|
+
} catch (e) {
|
|
149
|
+
console.error('Failed to set env:', e.message)
|
|
150
|
+
process.exit(1)
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
program
|
|
155
|
+
.command('server')
|
|
156
|
+
.option('--port <number>')
|
|
157
|
+
.option('--basicAuth', false)
|
|
158
|
+
.action((opts) => {
|
|
159
|
+
const portArg = opts.port ? `--port=${opts.port}` : ''
|
|
160
|
+
const basicAuthArg = opts.basicAuth ? '--basicAuth' : ''
|
|
161
|
+
const serverPath = path.join(__dirname, '..', 'server', 'src', 'index.ts')
|
|
162
|
+
const distPath = path.join(__dirname, '..', 'server', 'dist', 'index.js')
|
|
163
|
+
const finalPath = fs.existsSync(distPath) ? distPath : serverPath
|
|
164
|
+
if (finalPath.endsWith('.js')) {
|
|
165
|
+
require('child_process').fork(finalPath, [portArg, basicAuthArg].filter(Boolean), { stdio: 'inherit' })
|
|
166
|
+
} else {
|
|
167
|
+
const { spawn } = require('child_process')
|
|
168
|
+
const args = ['tsx', serverPath, portArg, basicAuthArg].filter(Boolean)
|
|
169
|
+
const child = spawn('npx', args, { stdio: 'inherit', shell: process.platform === 'win32' })
|
|
170
|
+
child.on('close', (code) => process.exit(code))
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
program.parse(process.argv)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { build } = require('esbuild')
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
|
|
6
|
+
const SRC = path.join(__dirname, 'src')
|
|
7
|
+
const DIST = path.join(__dirname, 'dist')
|
|
8
|
+
const ENTRY = path.join(SRC, 'cli', 'entry.js')
|
|
9
|
+
|
|
10
|
+
// Clean
|
|
11
|
+
fs.rmSync(DIST, { recursive: true, force: true })
|
|
12
|
+
fs.mkdirSync(DIST, { recursive: true })
|
|
13
|
+
|
|
14
|
+
async function main() {
|
|
15
|
+
// 1. Bundle CLI into a single executable
|
|
16
|
+
await build({
|
|
17
|
+
entryPoints: [ENTRY],
|
|
18
|
+
bundle: true,
|
|
19
|
+
platform: 'node',
|
|
20
|
+
target: 'node18',
|
|
21
|
+
outfile: path.join(DIST, 'cli.js'),
|
|
22
|
+
external: ['ws', 'commander'],
|
|
23
|
+
banner: { js: '#!/usr/bin/env node' },
|
|
24
|
+
})
|
|
25
|
+
fs.chmodSync(path.join(DIST, 'cli.js'), 0o755)
|
|
26
|
+
|
|
27
|
+
// 2. Bundle client library as CJS
|
|
28
|
+
await build({
|
|
29
|
+
entryPoints: [path.join(SRC, 'index.ts')],
|
|
30
|
+
bundle: true,
|
|
31
|
+
platform: 'node',
|
|
32
|
+
target: 'node18',
|
|
33
|
+
outfile: path.join(DIST, 'index.cjs'),
|
|
34
|
+
format: 'cjs',
|
|
35
|
+
external: ['ws'],
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// 3. Bundle client library as ESM
|
|
39
|
+
await build({
|
|
40
|
+
entryPoints: [path.join(SRC, 'index.ts')],
|
|
41
|
+
bundle: true,
|
|
42
|
+
platform: 'node',
|
|
43
|
+
target: 'node18',
|
|
44
|
+
outfile: path.join(DIST, 'index.mjs'),
|
|
45
|
+
format: 'esm',
|
|
46
|
+
external: ['ws'],
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
console.log('=== Built ===')
|
|
50
|
+
for (const entry of fs.readdirSync(DIST)) {
|
|
51
|
+
const p = path.join(DIST, entry)
|
|
52
|
+
const stat = fs.statSync(p)
|
|
53
|
+
console.log(` ${entry} (${stat.isDirectory() ? 'dir' : (stat.size / 1024).toFixed(1) + ' KB'})`)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
main().catch(e => { console.error(e); process.exit(1) })
|