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.
Files changed (36) hide show
  1. package/README.md +303 -0
  2. package/package.json +38 -0
  3. package/packages/cli/package.json +15 -0
  4. package/packages/cli/src/bin.js +228 -0
  5. package/packages/client/bin.js +174 -0
  6. package/packages/client/build.js +57 -0
  7. package/packages/client/dist/cli.js +1041 -0
  8. package/packages/client/dist/index.cjs +333 -0
  9. package/packages/client/dist/index.mjs +296 -0
  10. package/packages/client/package.json +24 -0
  11. package/packages/client/src/cli/bin.js +228 -0
  12. package/packages/client/src/cli/entry.js +465 -0
  13. package/packages/client/src/index.ts +31 -0
  14. package/packages/client/src/shared/buffer-shim.d.ts +4 -0
  15. package/packages/client/src/shared/crypto.ts +98 -0
  16. package/packages/client/src/shared/errors.ts +32 -0
  17. package/packages/client/src/shared/index.ts +3 -0
  18. package/packages/client/src/shared/types.ts +118 -0
  19. package/packages/client/src/ws-manager.ts +263 -0
  20. package/packages/server/package.json +21 -0
  21. package/packages/server/src/auth.ts +13 -0
  22. package/packages/server/src/db/index.ts +19 -0
  23. package/packages/server/src/db/interface.ts +33 -0
  24. package/packages/server/src/db/mongo.ts +166 -0
  25. package/packages/server/src/db/sqlite.ts +180 -0
  26. package/packages/server/src/index.ts +123 -0
  27. package/packages/server/src/pk-manager.ts +79 -0
  28. package/packages/server/src/routes/index.ts +110 -0
  29. package/packages/server/src/views/index.ejs +359 -0
  30. package/packages/server/src/ws/router.ts +263 -0
  31. package/packages/shared/package.json +13 -0
  32. package/packages/shared/src/buffer-shim.d.ts +4 -0
  33. package/packages/shared/src/crypto.ts +98 -0
  34. package/packages/shared/src/errors.ts +32 -0
  35. package/packages/shared/src/index.ts +3 -0
  36. 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) })