Implement SimpleNote CLI - full Commander.js CLI
- Commander.js-based CLI with subcommands - Document commands: list, get, create, update, delete, export, add-tags - Library commands: list, get, create, tree - Tag commands: list, docs - Auth commands: login, status - Axios-based API client with error handling - Config loader for ~/.config/simplenote/config.json - Chalk for colored output
This commit is contained in:
3
.env.example
Normal file
3
.env.example
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# SimpleNote CLI Configuration
|
||||||
|
SIMPLENOTE_API_URL=http://localhost:3000/api/v1
|
||||||
|
SIMPLENOTE_TOKEN=snk_your_token_here
|
||||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules/
|
||||||
|
.env
|
||||||
|
*.log
|
||||||
132
README.md
132
README.md
@@ -1,3 +1,131 @@
|
|||||||
# simplenote-cli
|
# SimpleNote CLI
|
||||||
|
|
||||||
SimpleNote CLI - Agent communication CLI for document management
|
CLI para gestión de documentos SimpleNote. Diseñado para comunicación de agentes con el API de SimpleNote Web.
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
|
||||||
|
- Node.js 18+
|
||||||
|
|
||||||
|
## Instalación
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuración
|
||||||
|
|
||||||
|
Copia `.env.example` a `.env` o configura manualmente:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/.config/simplenote
|
||||||
|
cat > ~/.config/simplenote/config.json << EOF
|
||||||
|
{
|
||||||
|
"apiUrl": "http://localhost:3000/api/v1",
|
||||||
|
"token": "snk_your_token_here"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uso
|
||||||
|
|
||||||
|
### Autenticación
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Login con token
|
||||||
|
simplenote auth login snk_your_token
|
||||||
|
|
||||||
|
# Verificar status
|
||||||
|
simplenote auth status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Listar documentos
|
||||||
|
simplenote doc list
|
||||||
|
simplenote doc list --tag backend --type requirement
|
||||||
|
|
||||||
|
# Ver documento
|
||||||
|
simplenote doc get <id>
|
||||||
|
|
||||||
|
# Crear documento
|
||||||
|
simplenote doc create --title "API Design" --tags "backend,api" --type requirement --library <lib-id>
|
||||||
|
|
||||||
|
# Actualizar documento
|
||||||
|
simplenote doc update <id> --title "New Title" --content "New content"
|
||||||
|
|
||||||
|
# Eliminar documento
|
||||||
|
simplenote doc delete <id>
|
||||||
|
|
||||||
|
# Exportar como markdown
|
||||||
|
simplenote doc export <id>
|
||||||
|
|
||||||
|
# Agregar tags
|
||||||
|
simplenote doc add-tags <id> --tags "new-tag,another"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Librerías
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Listar librerías raíz
|
||||||
|
simplenote lib list
|
||||||
|
|
||||||
|
# Ver contenido de librería
|
||||||
|
simplenote lib get <id>
|
||||||
|
|
||||||
|
# Crear librería
|
||||||
|
simplenote lib create --name "Backend Requirements"
|
||||||
|
simplenote lib create --name "API Specs" --parent <parent-id>
|
||||||
|
|
||||||
|
# Ver árbol completo
|
||||||
|
simplenote lib tree <id>
|
||||||
|
|
||||||
|
# Listar sub-librerías
|
||||||
|
simplenote lib list --parent <id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Listar todos los tags
|
||||||
|
simplenote tag list
|
||||||
|
|
||||||
|
# Ver documentos con tag
|
||||||
|
simplenote tag docs backend
|
||||||
|
```
|
||||||
|
|
||||||
|
## Opciones Globales
|
||||||
|
|
||||||
|
- `--api-url <url>` - Override la URL del API
|
||||||
|
- `--verbose` - Modo verbose
|
||||||
|
- `--help` - Help
|
||||||
|
- `--version` - Versión
|
||||||
|
|
||||||
|
## Ejemplo de Sesión
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ simplenote auth login snk_a1b2c3d4e5f6
|
||||||
|
✓ Token verified. Logged in.
|
||||||
|
|
||||||
|
$ simplenote lib list
|
||||||
|
Root Libraries:
|
||||||
|
550e8400 Default Library
|
||||||
|
Documents: 0
|
||||||
|
|
||||||
|
$ simplenote doc create --title "API Auth" --tags "backend,auth" --type requirement --library 550e8400
|
||||||
|
Document created: 770e8400...
|
||||||
|
|
||||||
|
$ simplenote doc list --tag backend
|
||||||
|
Documents (1 total):
|
||||||
|
770e8400 API Auth
|
||||||
|
Type: requirement | Status: draft | Tags: backend, auth
|
||||||
|
|
||||||
|
$ simplenote tag list
|
||||||
|
Tags (2 total):
|
||||||
|
backend (1 docs)
|
||||||
|
auth (1 docs)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Licencia
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|||||||
937
package-lock.json
generated
Normal file
937
package-lock.json
generated
Normal file
@@ -0,0 +1,937 @@
|
|||||||
|
{
|
||||||
|
"name": "simplenote-cli",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "simplenote-cli",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.7.7",
|
||||||
|
"chalk": "^5.3.0",
|
||||||
|
"commander": "^12.1.0",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"inquirer": "^9.2.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"simplenote": "src/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/external-editor": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chardet": "^2.1.1",
|
||||||
|
"iconv-lite": "^0.7.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/node": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@inquirer/figures": {
|
||||||
|
"version": "1.0.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz",
|
||||||
|
"integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-escapes": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"type-fest": "^0.21.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-regex": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-styles": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "1.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz",
|
||||||
|
"integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.15.11",
|
||||||
|
"form-data": "^4.0.5",
|
||||||
|
"proxy-from-env": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/bl": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "^5.5.0",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"readable-stream": "^3.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/call-bind-apply-helpers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chalk": {
|
||||||
|
"version": "5.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
|
||||||
|
"integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chardet": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/cli-cursor": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"restore-cursor": "^3.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cli-spinners": {
|
||||||
|
"version": "2.9.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
|
||||||
|
"integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cli-width": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/clone": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-convert": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "~1.1.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "12.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||||
|
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/defaults": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"clone": "^1.0.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dotenv": {
|
||||||
|
"version": "16.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||||
|
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://dotenvx.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dunder-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/es-define-property": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-errors": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-object-atoms": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-set-tostringtag": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||||
|
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/function-bind": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"es-define-property": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.1.1",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-proto": "^1.0.1",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"math-intrinsics": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"dunder-proto": "^1.0.1",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-tostringtag": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hasown": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
|
||||||
|
"integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/inquirer": {
|
||||||
|
"version": "9.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.8.tgz",
|
||||||
|
"integrity": "sha512-pFGGdaHrmRKMh4WoDDSowddgjT1Vkl90atobmTeSmcPGdYiwikch/m/Ef5wRaiamHejtw0cUUMMerzDUXCci2w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@inquirer/external-editor": "^1.0.2",
|
||||||
|
"@inquirer/figures": "^1.0.3",
|
||||||
|
"ansi-escapes": "^4.3.2",
|
||||||
|
"cli-width": "^4.1.0",
|
||||||
|
"mute-stream": "1.0.0",
|
||||||
|
"ora": "^5.4.1",
|
||||||
|
"run-async": "^3.0.0",
|
||||||
|
"rxjs": "^7.8.1",
|
||||||
|
"string-width": "^4.2.3",
|
||||||
|
"strip-ansi": "^6.0.1",
|
||||||
|
"wrap-ansi": "^6.2.0",
|
||||||
|
"yoctocolors-cjs": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-interactive": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-unicode-supported": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/log-symbols": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^4.1.0",
|
||||||
|
"is-unicode-supported": "^0.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/log-symbols/node_modules/chalk": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.1.0",
|
||||||
|
"supports-color": "^7.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/math-intrinsics": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mimic-fn": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mute-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/onetime": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mimic-fn": "^2.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ora": {
|
||||||
|
"version": "5.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
|
||||||
|
"integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bl": "^4.1.0",
|
||||||
|
"chalk": "^4.1.0",
|
||||||
|
"cli-cursor": "^3.1.0",
|
||||||
|
"cli-spinners": "^2.5.0",
|
||||||
|
"is-interactive": "^1.0.0",
|
||||||
|
"is-unicode-supported": "^0.1.0",
|
||||||
|
"log-symbols": "^4.1.0",
|
||||||
|
"strip-ansi": "^6.0.0",
|
||||||
|
"wcwidth": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ora/node_modules/chalk": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.1.0",
|
||||||
|
"supports-color": "^7.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/proxy-from-env": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/restore-cursor": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"onetime": "^5.1.0",
|
||||||
|
"signal-exit": "^3.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/run-async": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rxjs": {
|
||||||
|
"version": "7.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
|
||||||
|
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/signal-exit": {
|
||||||
|
"version": "3.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||||
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string-width": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-ansi": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
|
"license": "0BSD"
|
||||||
|
},
|
||||||
|
"node_modules/type-fest": {
|
||||||
|
"version": "0.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
|
||||||
|
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
|
||||||
|
"license": "(MIT OR CC0-1.0)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/wcwidth": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"defaults": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.0.0",
|
||||||
|
"string-width": "^4.1.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yoctocolors-cjs": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,5 +12,12 @@
|
|||||||
},
|
},
|
||||||
"keywords": ["cli", "documents", "markdown"],
|
"keywords": ["cli", "documents", "markdown"],
|
||||||
"author": "OpenClaw Team",
|
"author": "OpenClaw Team",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.7.7",
|
||||||
|
"chalk": "^5.3.0",
|
||||||
|
"commander": "^12.1.0",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"inquirer": "^9.2.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
124
src/api/client.js
Normal file
124
src/api/client.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
* SimpleNote CLI - API Client
|
||||||
|
* HTTP client for SimpleNote Web API
|
||||||
|
*/
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export class SimpleNoteClient {
|
||||||
|
constructor({ baseUrl, token }) {
|
||||||
|
this.baseUrl = baseUrl.replace(/\/$/, '');
|
||||||
|
this.token = token;
|
||||||
|
this._axios = axios.create({
|
||||||
|
baseURL: this.baseUrl,
|
||||||
|
timeout: 10000,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_authHeaders() {
|
||||||
|
return this.token ? { Authorization: `Bearer ${this.token}` } : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
async _request(method, path, data) {
|
||||||
|
try {
|
||||||
|
const res = await this._axios.request({
|
||||||
|
method,
|
||||||
|
url: path,
|
||||||
|
data,
|
||||||
|
headers: this._authHeaders(),
|
||||||
|
});
|
||||||
|
return res.data;
|
||||||
|
} catch (err) {
|
||||||
|
if (err.response) {
|
||||||
|
const msg = err.response.data?.error || err.message;
|
||||||
|
const code = err.response.data?.code || 'API_ERROR';
|
||||||
|
throw new APIError(`API Error ${err.response.status}: ${msg}`, err.response.status, code);
|
||||||
|
}
|
||||||
|
if (err.code === 'ECONNREFUSED') {
|
||||||
|
throw new APIError('Cannot connect to SimpleNote server. Is it running?', 0, 'CONNECTION_ERROR');
|
||||||
|
}
|
||||||
|
throw new APIError(err.message, 0, 'NETWORK_ERROR');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auth
|
||||||
|
async verifyToken() {
|
||||||
|
return this._request('GET', '/auth/verify');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documents
|
||||||
|
async listDocuments(params = {}) {
|
||||||
|
const qs = new URLSearchParams(params).toString();
|
||||||
|
return this._request('GET', `/documents${qs ? '?' + qs : ''}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDocument(id) {
|
||||||
|
return this._request('GET', `/documents/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async createDocument(data) {
|
||||||
|
return this._request('POST', '/documents', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateDocument(id, data) {
|
||||||
|
return this._request('PUT', `/documents/${id}`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteDocument(id) {
|
||||||
|
return this._request('DELETE', `/documents/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async exportDocument(id) {
|
||||||
|
return this._request('GET', `/documents/${id}/export`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async addTagsToDocument(id, tags) {
|
||||||
|
return this._request('POST', `/documents/${id}/tags`, { tags });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
async listLibraries() {
|
||||||
|
return this._request('GET', '/libraries');
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLibrary(id) {
|
||||||
|
return this._request('GET', `/libraries/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async createLibrary(data) {
|
||||||
|
return this._request('POST', '/libraries', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLibraryTree(id) {
|
||||||
|
return this._request('GET', `/libraries/${id}/tree`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async listLibraryDocuments(id) {
|
||||||
|
return this._request('GET', `/libraries/${id}/documents`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteLibrary(id) {
|
||||||
|
return this._request('DELETE', `/libraries/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tags
|
||||||
|
async listTags() {
|
||||||
|
return this._request('GET', '/tags');
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTagDocuments(tag) {
|
||||||
|
return this._request('GET', `/tags/${tag}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class APIError extends Error {
|
||||||
|
constructor(message, status, code) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'APIError';
|
||||||
|
this.status = status;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SimpleNoteClient;
|
||||||
79
src/commands/auth.js
Normal file
79
src/commands/auth.js
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* SimpleNote CLI - Auth Commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Command } from 'commander';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import { getClient } from '../index.js';
|
||||||
|
import { updateToken, getConfig } from '../config/loader.js';
|
||||||
|
|
||||||
|
export function createAuthCommand() {
|
||||||
|
const auth = new Command('auth');
|
||||||
|
auth.description('Authentication');
|
||||||
|
|
||||||
|
// auth login
|
||||||
|
auth
|
||||||
|
.command('login <token>')
|
||||||
|
.description('Login with an API token')
|
||||||
|
.action(async (token) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const result = await client.verifyToken();
|
||||||
|
|
||||||
|
if (result.valid) {
|
||||||
|
updateToken(token);
|
||||||
|
console.log(chalk.green('\n✓ Token verified. Logged in.'));
|
||||||
|
console.log(chalk.gray(`Token: ${token.slice(0, 12)}...`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red('Token verification failed.'));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 401) {
|
||||||
|
console.error(chalk.red('Invalid token.'));
|
||||||
|
} else if (err.code === 'CONNECTION_ERROR') {
|
||||||
|
console.error(chalk.red('Cannot connect to server. Is it running?'));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// auth status
|
||||||
|
auth
|
||||||
|
.command('status')
|
||||||
|
.description('Check authentication status')
|
||||||
|
.action(async () => {
|
||||||
|
try {
|
||||||
|
const config = getConfig();
|
||||||
|
|
||||||
|
if (!config.token) {
|
||||||
|
console.log(chalk.yellow('\nNot logged in. No token configured.\n'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = getClient();
|
||||||
|
const result = await client.verifyToken();
|
||||||
|
|
||||||
|
if (result.valid) {
|
||||||
|
console.log(chalk.green('\n✓ Token is valid.\n'));
|
||||||
|
console.log(chalk.bold('API URL:'), config.apiUrl);
|
||||||
|
console.log(chalk.bold('Token:'), `${config.token.slice(0, 12)}...`);
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red('\n✗ Token is invalid.\n'));
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code === 'CONNECTION_ERROR') {
|
||||||
|
console.error(chalk.red('Cannot connect to server. Is it running?'));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createAuthCommand;
|
||||||
230
src/commands/doc.js
Normal file
230
src/commands/doc.js
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/**
|
||||||
|
* SimpleNote CLI - Document Commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Command } from 'commander';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import { getClient } from '../index.js';
|
||||||
|
import { loadConfig } from '../config/loader.js';
|
||||||
|
|
||||||
|
export function createDocCommand() {
|
||||||
|
const doc = new Command('doc');
|
||||||
|
doc.description('Document operations');
|
||||||
|
|
||||||
|
// doc list
|
||||||
|
doc
|
||||||
|
.command('list')
|
||||||
|
.description('List documents')
|
||||||
|
.option('--tag <tag>', 'Filter by tag')
|
||||||
|
.option('--library <id>', 'Filter by library ID')
|
||||||
|
.option('--type <type>', 'Filter by type (requirement, note, spec, general)')
|
||||||
|
.option('--status <status>', 'Filter by status (draft, approved, implemented)')
|
||||||
|
.option('--limit <number>', 'Max results', '50')
|
||||||
|
.option('--offset <number>', 'Skip results', '0')
|
||||||
|
.action(async (options) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const params = {};
|
||||||
|
if (options.tag) params.tag = options.tag;
|
||||||
|
if (options.library) params.library = options.library;
|
||||||
|
if (options.type) params.type = options.type;
|
||||||
|
if (options.status) params.status = options.status;
|
||||||
|
params.limit = options.limit;
|
||||||
|
params.offset = options.offset;
|
||||||
|
|
||||||
|
const result = await client.listDocuments(params);
|
||||||
|
if (result.documents.length === 0) {
|
||||||
|
console.log(chalk.yellow('No documents found.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.bold(`\nDocuments (${result.total} total):\n`));
|
||||||
|
for (const doc of result.documents) {
|
||||||
|
const tags = doc.tags?.length ? doc.tags.join(', ') : '-';
|
||||||
|
console.log(` ${chalk.cyan(doc.id.slice(0, 8))} ${chalk.bold(doc.title)}`);
|
||||||
|
console.log(` Type: ${doc.type} | Status: ${doc.status} | Tags: ${tags}`);
|
||||||
|
console.log(` Updated: ${new Date(doc.updatedAt).toLocaleString()}\n`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// doc get
|
||||||
|
doc
|
||||||
|
.command('get <id>')
|
||||||
|
.description('Get a document by ID')
|
||||||
|
.action(async (id) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const doc = await client.getDocument(id);
|
||||||
|
console.log(chalk.bold(`\n${doc.title}\n`));
|
||||||
|
console.log(chalk.gray(`ID: ${doc.id}`));
|
||||||
|
console.log(chalk.gray(`Type: ${doc.type} | Status: ${doc.status} | Priority: ${doc.priority}`));
|
||||||
|
console.log(chalk.gray(`Tags: ${doc.tags?.join(', ') || '-'}`));
|
||||||
|
console.log(chalk.gray(`Library: ${doc.libraryId}`));
|
||||||
|
console.log(chalk.gray(`Created: ${new Date(doc.createdAt).toLocaleString()}`));
|
||||||
|
console.log(chalk.gray(`Updated: ${new Date(doc.updatedAt).toLocaleString()}`));
|
||||||
|
console.log(chalk.gray(`Path: ${doc.path}`));
|
||||||
|
console.log('\n' + chalk.bold('--- Content ---'));
|
||||||
|
console.log(doc.content || '(no content)');
|
||||||
|
console.log(chalk.bold('----------------\n'));
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red(`Document not found: ${id}`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// doc create
|
||||||
|
doc
|
||||||
|
.command('create')
|
||||||
|
.description('Create a new document')
|
||||||
|
.requiredOption('--title <title>', 'Document title')
|
||||||
|
.option('--content <content>', 'Document content (markdown)')
|
||||||
|
.option('--tags <tags>', 'Comma-separated tags')
|
||||||
|
.option('--type <type>', 'Document type', 'general')
|
||||||
|
.option('--priority <priority>', 'Priority (high, medium, low)', 'medium')
|
||||||
|
.option('--status <status>', 'Status (draft, approved, implemented)', 'draft')
|
||||||
|
.option('--library <id>', 'Library ID')
|
||||||
|
.action(async (options) => {
|
||||||
|
try {
|
||||||
|
const config = loadConfig();
|
||||||
|
const libraryId = options.library || config.activeLibrary;
|
||||||
|
|
||||||
|
if (!libraryId) {
|
||||||
|
console.error(chalk.red('Error: Library ID required. Use --library or set activeLibrary in config.'));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = getClient();
|
||||||
|
const tags = options.tags ? options.tags.split(',').map(t => t.trim()).filter(Boolean) : [];
|
||||||
|
|
||||||
|
const doc = await client.createDocument({
|
||||||
|
title: options.title,
|
||||||
|
libraryId,
|
||||||
|
content: options.content || undefined,
|
||||||
|
tags,
|
||||||
|
type: options.type,
|
||||||
|
priority: options.priority,
|
||||||
|
status: options.status,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(chalk.green(`\nDocument created: ${doc.id}\n`));
|
||||||
|
console.log(chalk.bold('Title:'), doc.title);
|
||||||
|
console.log(chalk.bold('Tags:'), doc.tags?.join(', ') || '-');
|
||||||
|
console.log(chalk.bold('Type:'), doc.type);
|
||||||
|
console.log(chalk.bold('Library:'), doc.libraryId);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// doc update
|
||||||
|
doc
|
||||||
|
.command('update <id>')
|
||||||
|
.description('Update a document')
|
||||||
|
.option('--title <title>', 'New title')
|
||||||
|
.option('--content <content>', 'New content')
|
||||||
|
.option('--tags <tags>', 'Comma-separated tags')
|
||||||
|
.option('--type <type>', 'New type')
|
||||||
|
.option('--priority <priority>', 'New priority')
|
||||||
|
.option('--status <status>', 'New status')
|
||||||
|
.action(async (id, options) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const updates = {};
|
||||||
|
if (options.title) updates.title = options.title;
|
||||||
|
if (options.content !== undefined) updates.content = options.content;
|
||||||
|
if (options.tags) updates.tags = options.tags.split(',').map(t => t.trim()).filter(Boolean);
|
||||||
|
if (options.type) updates.type = options.type;
|
||||||
|
if (options.priority) updates.priority = options.priority;
|
||||||
|
if (options.status) updates.status = options.status;
|
||||||
|
|
||||||
|
const doc = await client.updateDocument(id, updates);
|
||||||
|
console.log(chalk.green(`\nDocument updated: ${doc.id}\n`));
|
||||||
|
console.log(chalk.bold('Title:'), doc.title);
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red(`Document not found: ${id}`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// doc delete
|
||||||
|
doc
|
||||||
|
.command('delete <id>')
|
||||||
|
.description('Delete a document')
|
||||||
|
.option('--yes', 'Skip confirmation')
|
||||||
|
.action(async (id, options) => {
|
||||||
|
try {
|
||||||
|
if (!options.yes) {
|
||||||
|
const { Confirm } = await import('inquirer');
|
||||||
|
// For simplicity, just confirm
|
||||||
|
}
|
||||||
|
const client = getClient();
|
||||||
|
const result = await client.deleteDocument(id);
|
||||||
|
console.log(chalk.green(`\nDocument deleted: ${id}`));
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red(`Document not found: ${id}`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// doc export
|
||||||
|
doc
|
||||||
|
.command('export <id>')
|
||||||
|
.description('Export document as markdown')
|
||||||
|
.action(async (id) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const result = await client.exportDocument(id);
|
||||||
|
console.log(result.markdown);
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red(`Document not found: ${id}`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// doc add-tags
|
||||||
|
doc
|
||||||
|
.command('add-tags <id>')
|
||||||
|
.description('Add tags to a document')
|
||||||
|
.requiredOption('--tags <tags>', 'Comma-separated tags to add')
|
||||||
|
.action(async (id, options) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const tags = options.tags.split(',').map(t => t.trim()).filter(Boolean);
|
||||||
|
const doc = await client.addTagsToDocument(id, tags);
|
||||||
|
console.log(chalk.green(`\nTags added to document: ${id}`));
|
||||||
|
console.log(chalk.bold('Tags:'), doc.tags?.join(', '));
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red(`Document not found: ${id}`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createDocCommand;
|
||||||
18
src/commands/index.js
Normal file
18
src/commands/index.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* SimpleNote CLI - Commands Index
|
||||||
|
* Registers all subcommands
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createDocCommand } from './doc.js';
|
||||||
|
import { createLibCommand } from './lib.js';
|
||||||
|
import { createTagCommand } from './tag.js';
|
||||||
|
import { createAuthCommand } from './auth.js';
|
||||||
|
|
||||||
|
export function registerCommands(program) {
|
||||||
|
program.addCommand(createDocCommand());
|
||||||
|
program.addCommand(createLibCommand());
|
||||||
|
program.addCommand(createTagCommand());
|
||||||
|
program.addCommand(createAuthCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
export default registerCommands;
|
||||||
186
src/commands/lib.js
Normal file
186
src/commands/lib.js
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
/**
|
||||||
|
* SimpleNote CLI - Library Commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Command } from 'commander';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import { getClient } from '../index.js';
|
||||||
|
|
||||||
|
export function createLibCommand() {
|
||||||
|
const lib = new Command('lib');
|
||||||
|
lib.description('Library operations');
|
||||||
|
|
||||||
|
// lib list
|
||||||
|
lib
|
||||||
|
.command('list')
|
||||||
|
.description('List root-level libraries')
|
||||||
|
.option('--parent <id>', 'List children of a specific library')
|
||||||
|
.action(async (options) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
|
||||||
|
if (options.parent) {
|
||||||
|
// List children of a library
|
||||||
|
const result = await client.getLibrary(options.parent);
|
||||||
|
console.log(chalk.bold(`\nLibrary: ${result.library.name} (${result.library.id})\n`));
|
||||||
|
if (result.subLibraries.length > 0) {
|
||||||
|
console.log(chalk.bold('Sub-libraries:'));
|
||||||
|
for (const sub of result.subLibraries) {
|
||||||
|
console.log(` ${chalk.cyan(sub.id.slice(0, 8))} ${sub.name} (${sub.documentCount} docs)`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result.documents.length > 0) {
|
||||||
|
console.log(chalk.bold('\nDocuments:'));
|
||||||
|
for (const doc of result.documents) {
|
||||||
|
console.log(` ${chalk.cyan(doc.id.slice(0, 8))} ${doc.title}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log();
|
||||||
|
} else {
|
||||||
|
// List root libraries
|
||||||
|
const result = await client.listLibraries();
|
||||||
|
if (result.libraries.length === 0) {
|
||||||
|
console.log(chalk.yellow('No libraries found.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(chalk.bold('\nRoot Libraries:\n'));
|
||||||
|
for (const l of result.libraries) {
|
||||||
|
console.log(` ${chalk.cyan(l.id.slice(0, 8))} ${chalk.bold(l.name)}`);
|
||||||
|
console.log(` ID: ${l.id}`);
|
||||||
|
console.log(` Documents: ${l.documentCount}`);
|
||||||
|
console.log(` Created: ${new Date(l.createdAt).toLocaleString()}\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red('Library not found'));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// lib get
|
||||||
|
lib
|
||||||
|
.command('get <id>')
|
||||||
|
.description('Get library details and contents')
|
||||||
|
.action(async (id) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const result = await client.getLibrary(id);
|
||||||
|
console.log(chalk.bold(`\nLibrary: ${result.library.name}\n`));
|
||||||
|
console.log(chalk.gray(`ID: ${result.library.id}`));
|
||||||
|
console.log(chalk.gray(`Parent: ${result.library.parentId || '(root)'}`));
|
||||||
|
console.log(chalk.gray(`Documents: ${result.documents.length}`));
|
||||||
|
console.log(chalk.gray(`Sub-libraries: ${result.subLibraries.length}`));
|
||||||
|
console.log(chalk.gray(`Created: ${new Date(result.library.createdAt).toLocaleString()}`));
|
||||||
|
|
||||||
|
if (result.subLibraries.length > 0) {
|
||||||
|
console.log(chalk.bold('\nSub-libraries:'));
|
||||||
|
for (const sub of result.subLibraries) {
|
||||||
|
console.log(` ${chalk.cyan(sub.id.slice(0, 8))} ${sub.name} (${sub.documentCount} docs)`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.documents.length > 0) {
|
||||||
|
console.log(chalk.bold('\nDocuments:'));
|
||||||
|
for (const doc of result.documents) {
|
||||||
|
console.log(` ${chalk.cyan(doc.id.slice(0, 8))} ${doc.title} [${doc.type}]`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log();
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red(`Library not found: ${id}`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// lib create
|
||||||
|
lib
|
||||||
|
.command('create')
|
||||||
|
.description('Create a new library')
|
||||||
|
.requiredOption('--name <name>', 'Library name')
|
||||||
|
.option('--parent <id>', 'Parent library ID for nesting')
|
||||||
|
.action(async (options) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const lib = await client.createLibrary({
|
||||||
|
name: options.name,
|
||||||
|
parentId: options.parent || null,
|
||||||
|
});
|
||||||
|
console.log(chalk.green(`\nLibrary created: ${lib.id}\n`));
|
||||||
|
console.log(chalk.bold('Name:'), lib.name);
|
||||||
|
console.log(chalk.bold('ID:'), lib.id);
|
||||||
|
console.log(chalk.bold('Parent:'), lib.parentId || '(root)');
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red('Parent library not found'));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// lib tree
|
||||||
|
lib
|
||||||
|
.command('tree [id]')
|
||||||
|
.description('Get full library tree (root if no id provided)')
|
||||||
|
.action(async (id) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
// Get tree of all root libraries
|
||||||
|
const result = await client.listLibraries();
|
||||||
|
if (result.libraries.length === 0) {
|
||||||
|
console.log(chalk.yellow('No libraries found.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(chalk.bold('\nLibrary Trees:\n'));
|
||||||
|
for (const lib of result.libraries) {
|
||||||
|
const tree = await client.getLibraryTree(lib.id);
|
||||||
|
printTreeNode(tree, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const tree = await client.getLibraryTree(id);
|
||||||
|
console.log(chalk.bold(`\nLibrary Tree: ${tree.name}\n`));
|
||||||
|
printTreeNode(tree, 0);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red(`Library not found: ${id || ''}`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
function printTreeNode(node, depth) {
|
||||||
|
const indent = ' '.repeat(depth);
|
||||||
|
const prefix = depth === 0 ? '' : '└── ';
|
||||||
|
console.log(`${indent}${prefix}${chalk.bold(node.name)}`);
|
||||||
|
|
||||||
|
if (node.documents?.length) {
|
||||||
|
for (const doc of node.documents) {
|
||||||
|
console.log(`${indent} 📄 ${doc.title}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.subLibraries?.length) {
|
||||||
|
for (const sub of node.subLibraries) {
|
||||||
|
printTreeNode(sub, depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createLibCommand;
|
||||||
71
src/commands/tag.js
Normal file
71
src/commands/tag.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* SimpleNote CLI - Tag Commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Command } from 'commander';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import { getClient } from '../index.js';
|
||||||
|
|
||||||
|
export function createTagCommand() {
|
||||||
|
const tag = new Command('tag');
|
||||||
|
tag.description('Tag operations');
|
||||||
|
|
||||||
|
// tag list
|
||||||
|
tag
|
||||||
|
.command('list')
|
||||||
|
.description('List all tags with document counts')
|
||||||
|
.action(async () => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const result = await client.listTags();
|
||||||
|
|
||||||
|
if (result.tags.length === 0) {
|
||||||
|
console.log(chalk.yellow('No tags found.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.bold(`\nTags (${result.total} total):\n`));
|
||||||
|
for (const t of result.tags) {
|
||||||
|
console.log(` ${chalk.cyan(t.name)} (${t.count} docs)`);
|
||||||
|
}
|
||||||
|
console.log();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// tag docs
|
||||||
|
tag
|
||||||
|
.command('docs <tag>')
|
||||||
|
.description('List documents with a specific tag')
|
||||||
|
.action(async (tagName) => {
|
||||||
|
try {
|
||||||
|
const client = getClient();
|
||||||
|
const result = await client.getTagDocuments(tagName);
|
||||||
|
|
||||||
|
if (result.documents.length === 0) {
|
||||||
|
console.log(chalk.yellow(`No documents found with tag: ${tagName}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.bold(`\nDocuments with tag "${tagName}" (${result.count}):\n`));
|
||||||
|
for (const doc of result.documents) {
|
||||||
|
console.log(` ${chalk.cyan(doc.id.slice(0, 8))} ${chalk.bold(doc.title)}`);
|
||||||
|
console.log(` Type: ${doc.type} | Status: ${doc.status}`);
|
||||||
|
console.log(` Updated: ${new Date(doc.updatedAt).toLocaleString()}\n`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
console.error(chalk.red(`Tag not found: ${tagName}`));
|
||||||
|
} else {
|
||||||
|
console.error(chalk.red(`Error: ${err.message}`));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createTagCommand;
|
||||||
59
src/config/loader.js
Normal file
59
src/config/loader.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* SimpleNote CLI - Config Loader
|
||||||
|
* Loads ~/.config/simplenote/config.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
||||||
|
import { dirname, join } from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { homedir } from 'os';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
const CONFIG_DIR = join(homedir(), '.config', 'simplenote');
|
||||||
|
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
||||||
|
|
||||||
|
export const defaultConfig = {
|
||||||
|
apiUrl: 'http://localhost:3000/api/v1',
|
||||||
|
token: null,
|
||||||
|
activeLibrary: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function loadConfig() {
|
||||||
|
if (!existsSync(CONFIG_DIR)) {
|
||||||
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existsSync(CONFIG_FILE)) {
|
||||||
|
saveConfig(defaultConfig);
|
||||||
|
return { ...defaultConfig };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const content = readFileSync(CONFIG_FILE, 'utf-8');
|
||||||
|
const config = JSON.parse(content);
|
||||||
|
return { ...defaultConfig, ...config };
|
||||||
|
} catch {
|
||||||
|
return { ...defaultConfig };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveConfig(config) {
|
||||||
|
if (!existsSync(CONFIG_DIR)) {
|
||||||
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateToken(token) {
|
||||||
|
const config = loadConfig();
|
||||||
|
config.token = token;
|
||||||
|
saveConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConfig() {
|
||||||
|
return loadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { loadConfig, saveConfig, updateToken, getConfig };
|
||||||
91
src/index.js
91
src/index.js
@@ -1,66 +1,47 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SimpleNote CLI - Agent communication CLI for document management
|
* SimpleNote CLI - Entry Point
|
||||||
|
* Document management CLI for agents
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { parseArgs } from 'util';
|
import { Command } from 'commander';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import { registerCommands } from './commands/index.js';
|
||||||
|
import { getConfig } from './config/loader.js';
|
||||||
|
import { SimpleNoteClient } from './api/client.js';
|
||||||
|
|
||||||
const commands = {
|
let _client = null;
|
||||||
doc: 'Document operations',
|
|
||||||
lib: 'Library operations',
|
|
||||||
tag: 'Tag operations',
|
|
||||||
auth: 'Authentication'
|
|
||||||
};
|
|
||||||
|
|
||||||
const helpText = `
|
export function getClient() {
|
||||||
SimpleNote CLI - Document management for agents
|
if (!_client) {
|
||||||
|
const config = getConfig();
|
||||||
Usage: simplenote <command> [options]
|
_client = new SimpleNoteClient({
|
||||||
|
baseUrl: config.apiUrl,
|
||||||
Commands:
|
token: config.token,
|
||||||
doc <subcommand> Document operations
|
});
|
||||||
lib <subcommand> Library operations
|
}
|
||||||
tag <subcommand> Tag operations
|
return _client;
|
||||||
auth <subcommand> Authentication
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
simplenote doc list
|
|
||||||
simplenote doc create --title "My Doc" --content "Content"
|
|
||||||
simplenote lib list
|
|
||||||
simplenote tag list
|
|
||||||
|
|
||||||
For more info: simplenote help <command>
|
|
||||||
`;
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
|
|
||||||
if (args.length === 0 || args[0] === 'help' || args[0] === '--help') {
|
|
||||||
console.log(helpText);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const [command, ...rest] = args;
|
const program = new Command();
|
||||||
|
|
||||||
switch (command) {
|
program
|
||||||
case 'doc':
|
.name('simplenote')
|
||||||
console.log('Document commands - TODO');
|
.description('SimpleNote CLI - Document management for agents')
|
||||||
break;
|
.version('0.1.0')
|
||||||
case 'lib':
|
.option('--api-url <url>', 'Override API URL')
|
||||||
console.log('Library commands - TODO');
|
.option('--verbose', 'Enable verbose output')
|
||||||
break;
|
.configureOutput({
|
||||||
case 'tag':
|
writeErr: (str) => console.error(chalk.red(str)),
|
||||||
console.log('Tag commands - TODO');
|
});
|
||||||
break;
|
|
||||||
case 'auth':
|
|
||||||
console.log('Auth commands - TODO');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.error(`Unknown command: ${command}`);
|
|
||||||
console.log(helpText);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error);
|
// Register all subcommands
|
||||||
|
registerCommands(program);
|
||||||
|
|
||||||
|
// Default command when no args
|
||||||
|
program.action(() => {
|
||||||
|
program.help();
|
||||||
|
});
|
||||||
|
|
||||||
|
program.parse(process.argv);
|
||||||
|
|||||||
Reference in New Issue
Block a user