feat(interactive): Add interactive console features and refactor spinner module by renaming source-ora to source-interactive and removing ora dependency
This commit is contained in:
parent
09da3a1e2d
commit
7e8a404fcf
@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-05-15 - 3.1.0 - feat(interactive)
|
||||
Add interactive console features and refactor spinner module by renaming source-ora to source-interactive and removing ora dependency
|
||||
|
||||
- Renamed source-ora module to source-interactive and updated package.json exports
|
||||
- Removed ora dependency in favor of a custom spinner implementation
|
||||
- Added new progress bar functionality with configurable options including ETA, percentage, and color
|
||||
- Updated tests and documentation (README and plan) to reflect the new interactive features
|
||||
- Bumped dependency versions in package.json and improved test script configuration
|
||||
|
||||
## 2025-05-12 - 3.0.9 - fix(test/destination-devtools.browser)
|
||||
Simplify DevTools browser tests by removing redundant styled log assertions.
|
||||
|
||||
|
13
package.json
13
package.json
@ -25,7 +25,7 @@
|
||||
},
|
||||
"./context": "./dist_ts_context/index.js",
|
||||
"./interfaces": "./dist_ts_interfaces/index.js",
|
||||
"./source-ora": "./dist_ts_source_ora/index.js",
|
||||
"./source-interactive": "./dist_ts_source_interactive/index.js",
|
||||
"./destination-clickhouse": "./dist_ts_destination_clickhouse/index.js",
|
||||
"./destination-devtools": "./dist_ts_destination_devtools/index.js",
|
||||
"./destination-file": "./dist_ts_destination_file/index.js",
|
||||
@ -36,18 +36,18 @@
|
||||
"author": "Lossless GmbH",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "(tstest test/)",
|
||||
"test": "(tstest test/**/*.ts --verbose)",
|
||||
"build": "(tsbuild tsfolders --allowimplicitany && tsbundle npm)",
|
||||
"format": "(gitzone format)",
|
||||
"buildDocs": "tsdoc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^2.3.2",
|
||||
"@git.zone/tsbuild": "^2.5.1",
|
||||
"@git.zone/tsbundle": "^2.2.5",
|
||||
"@git.zone/tsrun": "^1.3.3",
|
||||
"@git.zone/tstest": "^1.0.96",
|
||||
"@git.zone/tstest": "^1.4.0",
|
||||
"@push.rocks/tapbundle": "^6.0.3",
|
||||
"@types/node": "^22.15.17"
|
||||
"@types/node": "^22.15.18"
|
||||
},
|
||||
"dependencies": {
|
||||
"@api.global/typedrequest-interfaces": "^3.0.19",
|
||||
@ -59,8 +59,7 @@
|
||||
"@push.rocks/smartpromise": "^4.2.3",
|
||||
"@push.rocks/smarttime": "^4.1.1",
|
||||
"@push.rocks/webrequest": "^3.0.37",
|
||||
"@tsclass/tsclass": "^9.2.0",
|
||||
"ora": "^8.2.0"
|
||||
"@tsclass/tsclass": "^9.2.0"
|
||||
},
|
||||
"files": [
|
||||
"ts/**/*",
|
||||
|
256
pnpm-lock.yaml
generated
256
pnpm-lock.yaml
generated
@ -38,13 +38,10 @@ importers:
|
||||
'@tsclass/tsclass':
|
||||
specifier: ^9.2.0
|
||||
version: 9.2.0
|
||||
ora:
|
||||
specifier: ^8.2.0
|
||||
version: 8.2.0
|
||||
devDependencies:
|
||||
'@git.zone/tsbuild':
|
||||
specifier: ^2.3.2
|
||||
version: 2.3.2
|
||||
specifier: ^2.5.1
|
||||
version: 2.5.1
|
||||
'@git.zone/tsbundle':
|
||||
specifier: ^2.2.5
|
||||
version: 2.2.5
|
||||
@ -52,14 +49,14 @@ importers:
|
||||
specifier: ^1.3.3
|
||||
version: 1.3.3
|
||||
'@git.zone/tstest':
|
||||
specifier: ^1.0.96
|
||||
version: 1.0.96(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)(typescript@5.7.3)
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)(typescript@5.7.3)
|
||||
'@push.rocks/tapbundle':
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)
|
||||
'@types/node':
|
||||
specifier: ^22.15.17
|
||||
version: 22.15.17
|
||||
specifier: ^22.15.18
|
||||
version: 22.15.18
|
||||
|
||||
packages:
|
||||
|
||||
@ -256,8 +253,8 @@ packages:
|
||||
resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@cloudflare/workers-types@4.20250508.0':
|
||||
resolution: {integrity: sha512-Gr7NLsHy5BFXbWVMMO+1mf/DwxT30tNw5LGhC86S+CXErM2a2eJ0HJHqgAs0Y8Lt/XEUSrH9QrUFDvJWNhE4Rg==}
|
||||
'@cloudflare/workers-types@4.20250515.0':
|
||||
resolution: {integrity: sha512-KoHFMH04gOXp3KEI+wrFIU+3ZfoSXnwqZTpybNQjalHoN3pWjtWBb/030cCRAZ639YX+DAHAxNF7AvEYGz1oaA==}
|
||||
|
||||
'@colors/colors@1.6.0':
|
||||
resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
|
||||
@ -581,8 +578,8 @@ packages:
|
||||
'@esm-bundle/chai@4.3.4-fix.0':
|
||||
resolution: {integrity: sha512-26SKdM4uvDWlY8/OOOxSB1AqQWeBosCX3wRYUZO7enTAj03CtVxIiCimYVG2WpULcyV51qapK4qTovwkUr5Mlw==}
|
||||
|
||||
'@git.zone/tsbuild@2.3.2':
|
||||
resolution: {integrity: sha512-PG7N39/MkpIKGgRvT2MC7eyLHMcoofaQJQgUlJzicp62Wfk2W9qbnI8Xexb52uy7zvmndao/G4xZ391exJAj+A==}
|
||||
'@git.zone/tsbuild@2.5.1':
|
||||
resolution: {integrity: sha512-b1TyaNnaPCD3dvdRZ2da0MkZbH9liCrhzg57pwFIB2Gx4g8UMv8ZLN2cA1NRaNE0o8NCybf3gV1L+V0FO0DrMQ==}
|
||||
hasBin: true
|
||||
|
||||
'@git.zone/tsbundle@2.2.5':
|
||||
@ -597,8 +594,8 @@ packages:
|
||||
resolution: {integrity: sha512-DDzWunkxXLtXJTxBf4EioXLwhuqdA2VzdTmOzWrw4Z4Qnms/YM67q36yajwNohAajPYyRz5DayU0ikrceFXyVw==}
|
||||
hasBin: true
|
||||
|
||||
'@git.zone/tstest@1.0.96':
|
||||
resolution: {integrity: sha512-c1FlIiRmMiLB56BP5JlPrJ9VTYCSjOjA7v0avVMAjLqBl06GB3Urun0sAXHjcjr2h5lOmTiw0KprRlJ7KF2XFA==}
|
||||
'@git.zone/tstest@1.4.0':
|
||||
resolution: {integrity: sha512-mTtKrXCB0oeAwIN56UNhQzRt1Fj8gWZRMK+NTIRC+/p5+Dqc6TBGVZ8bAv89vv7VKkgYuYjerxdN07H6UW+3Fg==}
|
||||
hasBin: true
|
||||
|
||||
'@hapi/bourne@3.0.0':
|
||||
@ -779,9 +776,6 @@ packages:
|
||||
'@push.rocks/smartexit@1.0.23':
|
||||
resolution: {integrity: sha512-WmwKYcwbHBByoABhHHB+PAjr5475AtD/xBh1mDcqPrFsOOUOZq3BBUdpq25wI3ccu/SZB5IwaimiVzadls6HkA==}
|
||||
|
||||
'@push.rocks/smartexpect@1.6.1':
|
||||
resolution: {integrity: sha512-NFQXEPkGiMNxyvFwKyzDWe3ADYdf8KNvIcV7TGNZZT3uPQtk65te4Q+a1cWErjP/61yE9XdYiQA66QQp+TV9IQ==}
|
||||
|
||||
'@push.rocks/smartexpect@2.4.2':
|
||||
resolution: {integrity: sha512-L+aS1n5rWhf/yOh5R3zPgwycYtDr5FfrDWgasy6ShhN6Zbn/z/AOPbWcF/OpeTmx0XabWB2h5d4xBcCKLl47cQ==}
|
||||
|
||||
@ -821,6 +815,9 @@ packages:
|
||||
'@push.rocks/smartlog@3.0.7':
|
||||
resolution: {integrity: sha512-WHOw0iHHjCEbYY4KGX40iFtLI11QJvvWIbC9yFn3Mt+nrdupMnry7Ztc5v/PqO8lu33Q6xDBMXiNQ9yNY0HVGw==}
|
||||
|
||||
'@push.rocks/smartlog@3.0.9':
|
||||
resolution: {integrity: sha512-B/YIJrwXsbxPkAJly8+55yx3Eqm5bIaCZ/xD2oe6fD8Zp58VLF2P8hpoQZJOiSO+KI7wXVlTEFHsmt8fpRZIVA==}
|
||||
|
||||
'@push.rocks/smartmanifest@2.0.2':
|
||||
resolution: {integrity: sha512-QGc5C9vunjfUbYsPGz5bynV/mVmPHkrQDkWp8ZO8VJtK1GZe+njgbrNyxn2SUHR0IhSAbSXl1j4JvBqYf5eTVg==}
|
||||
|
||||
@ -926,9 +923,6 @@ packages:
|
||||
'@push.rocks/smartyaml@2.0.5':
|
||||
resolution: {integrity: sha512-tBcf+HaOIfeEsTMwgUZDtZERCxXQyRsWO8Ar5DjBdiSRchbhVGZQEBzXswMS0W5ZoRenjgPK+4tPW3JQGRTfbg==}
|
||||
|
||||
'@push.rocks/tapbundle@5.6.3':
|
||||
resolution: {integrity: sha512-hFzsf59rg1K70i45llj7PCyyCZp7JW19XRR+Q1gge1T0pBN8Wi53aYqP/2qtxdMiNVe2s3ESp6VJZv3sLOMYPQ==}
|
||||
|
||||
'@push.rocks/tapbundle@6.0.3':
|
||||
resolution: {integrity: sha512-SuP14V6TPdtd1y1CYTvwTKJdpHa7EzY55NfaaEMxW4oRKvHgJiOiPEiR/IrtL9tSiDMSfrx12waTMgZheYaBug==}
|
||||
|
||||
@ -1463,8 +1457,8 @@ packages:
|
||||
'@types/node-forge@1.3.11':
|
||||
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
|
||||
|
||||
'@types/node@22.15.17':
|
||||
resolution: {integrity: sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==}
|
||||
'@types/node@22.15.18':
|
||||
resolution: {integrity: sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==}
|
||||
|
||||
'@types/parse5@6.0.3':
|
||||
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
|
||||
@ -1683,8 +1677,8 @@ packages:
|
||||
bare-events@2.5.4:
|
||||
resolution: {integrity: sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==}
|
||||
|
||||
bare-fs@4.1.4:
|
||||
resolution: {integrity: sha512-r8+26Voz8dGX3AYpJdFb1ZPaUSM8XOLCZvy+YGpRTmwPHIxA7Z3Jov/oMPtV7hfRQbOnH8qGlLTzQAbgtdNN0Q==}
|
||||
bare-fs@4.1.5:
|
||||
resolution: {integrity: sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==}
|
||||
engines: {bare: '>=1.16.0'}
|
||||
peerDependencies:
|
||||
bare-buffer: '*'
|
||||
@ -2051,6 +2045,15 @@ packages:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
debug@4.4.1:
|
||||
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
decode-named-character-reference@1.1.0:
|
||||
resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==}
|
||||
|
||||
@ -2319,8 +2322,8 @@ packages:
|
||||
resolution: {integrity: sha512-cB507r5T3D55DfclY01GLkninZLfU7HXV/mhVRTnTRm5k2u+fY7Fof2dBkr80p5t7G7dlA/G5dI87QiMdPpMCQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
fake-indexeddb@6.0.0:
|
||||
resolution: {integrity: sha512-YEboHE5VfopUclOck7LncgIqskAqnv4q0EWbYCaxKKjAvO93c+TJIaBuGy8CBFdbg9nKdpN3AuPRwVBJ4k7NrQ==}
|
||||
fake-indexeddb@6.0.1:
|
||||
resolution: {integrity: sha512-He2AjQGHe46svIFq5+L2Nx/eHDTI1oKgoevBP+TthnjymXiKkeJQ3+ITeWey99Y5+2OaPFbI1qEsx/5RsGtWnQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
fast-deep-equal@3.1.3:
|
||||
@ -2605,8 +2608,8 @@ packages:
|
||||
resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
http-cache-semantics@4.1.1:
|
||||
resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
|
||||
http-cache-semantics@4.2.0:
|
||||
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
|
||||
|
||||
http-errors@1.6.3:
|
||||
resolution: {integrity: sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=}
|
||||
@ -2779,10 +2782,6 @@ packages:
|
||||
resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
is-unicode-supported@2.0.0:
|
||||
resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
is-unicode-supported@2.1.0:
|
||||
resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
|
||||
engines: {node: '>=18'}
|
||||
@ -2920,8 +2919,8 @@ packages:
|
||||
kuler@2.0.0:
|
||||
resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==}
|
||||
|
||||
lenis@1.3.1:
|
||||
resolution: {integrity: sha512-OGRlQk7EkGUtjDdnH+U49Mp26G/wGJFHuyYJ8ZwATllwHQZOKYbeuVaPWYQ4lK0gHfAnk2m0u8qN8Y4dtrHaHw==}
|
||||
lenis@1.3.3:
|
||||
resolution: {integrity: sha512-DOopj/UKHS54E9l2g4BOpDUvsyvkd1zkv+ECtHxQ9Fto8ozzKSz7MccqT+KOyG0ABA/OHXZ7l9INx0peUoQ8rQ==}
|
||||
peerDependencies:
|
||||
'@nuxt/kit': '>=3.0.0'
|
||||
react: '>=17.0.0'
|
||||
@ -3826,6 +3825,11 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
semver@7.7.2:
|
||||
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
send@0.19.0:
|
||||
resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@ -4395,7 +4399,7 @@ snapshots:
|
||||
'@api.global/typedrequest': 3.1.10
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@api.global/typedsocket': 3.0.1
|
||||
'@cloudflare/workers-types': 4.20250508.0
|
||||
'@cloudflare/workers-types': 4.20250515.0
|
||||
'@design.estate/dees-comms': 1.0.27
|
||||
'@push.rocks/lik': 6.2.2
|
||||
'@push.rocks/smartchok': 1.0.34
|
||||
@ -4404,7 +4408,7 @@ snapshots:
|
||||
'@push.rocks/smartfeed': 1.0.11
|
||||
'@push.rocks/smartfile': 11.2.0
|
||||
'@push.rocks/smartjson': 5.0.20
|
||||
'@push.rocks/smartlog': 3.0.7
|
||||
'@push.rocks/smartlog': 3.0.9
|
||||
'@push.rocks/smartlog-destination-devtools': 1.0.12
|
||||
'@push.rocks/smartlog-interfaces': 3.0.2
|
||||
'@push.rocks/smartmanifest': 2.0.2
|
||||
@ -5008,7 +5012,7 @@ snapshots:
|
||||
dependencies:
|
||||
regenerator-runtime: 0.14.1
|
||||
|
||||
'@cloudflare/workers-types@4.20250508.0': {}
|
||||
'@cloudflare/workers-types@4.20250515.0': {}
|
||||
|
||||
'@colors/colors@1.6.0': {}
|
||||
|
||||
@ -5046,7 +5050,7 @@ snapshots:
|
||||
'@push.rocks/webrequest': 3.0.37
|
||||
'@push.rocks/websetup': 3.0.19
|
||||
'@push.rocks/webstore': 2.0.20
|
||||
lenis: 1.3.1
|
||||
lenis: 1.3.3
|
||||
lit: 3.3.0
|
||||
sweet-scroll: 4.0.0
|
||||
transitivePeerDependencies:
|
||||
@ -5221,14 +5225,14 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/chai': 4.3.20
|
||||
|
||||
'@git.zone/tsbuild@2.3.2':
|
||||
'@git.zone/tsbuild@2.5.1':
|
||||
dependencies:
|
||||
'@git.zone/tspublish': 1.9.1
|
||||
'@push.rocks/early': 4.0.4
|
||||
'@push.rocks/smartcli': 4.0.11
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartfile': 11.2.0
|
||||
'@push.rocks/smartlog': 3.0.7
|
||||
'@push.rocks/smartlog': 3.0.9
|
||||
'@push.rocks/smartpath': 5.0.18
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
typescript: 5.7.3
|
||||
@ -5258,7 +5262,7 @@ snapshots:
|
||||
'@push.rocks/smartcli': 4.0.11
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartfile': 11.2.0
|
||||
'@push.rocks/smartlog': 3.0.7
|
||||
'@push.rocks/smartlog': 3.0.9
|
||||
'@push.rocks/smartnpm': 2.0.4
|
||||
'@push.rocks/smartpath': 5.0.18
|
||||
'@push.rocks/smartrequest': 2.1.0
|
||||
@ -5272,7 +5276,7 @@ snapshots:
|
||||
'@push.rocks/smartshell': 3.2.3
|
||||
tsx: 4.19.4
|
||||
|
||||
'@git.zone/tstest@1.0.96(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)(typescript@5.7.3)':
|
||||
'@git.zone/tstest@1.4.0(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)(typescript@5.7.3)':
|
||||
dependencies:
|
||||
'@api.global/typedserver': 3.0.74
|
||||
'@git.zone/tsbundle': 2.2.5
|
||||
@ -5281,10 +5285,10 @@ snapshots:
|
||||
'@push.rocks/smartbrowser': 2.0.8(typescript@5.7.3)
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartfile': 11.2.0
|
||||
'@push.rocks/smartlog': 3.0.7
|
||||
'@push.rocks/smartlog': 3.0.9
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartshell': 3.2.3
|
||||
'@push.rocks/tapbundle': 5.6.3(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)
|
||||
'@push.rocks/tapbundle': 6.0.3(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)
|
||||
'@types/ws': 8.18.1
|
||||
figures: 6.1.0
|
||||
ws: 8.18.2
|
||||
@ -5334,7 +5338,7 @@ snapshots:
|
||||
'@jest/schemas': 29.6.3
|
||||
'@types/istanbul-lib-coverage': 2.0.6
|
||||
'@types/istanbul-reports': 3.0.4
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
'@types/yargs': 17.0.33
|
||||
chalk: 4.1.2
|
||||
|
||||
@ -5451,11 +5455,11 @@ snapshots:
|
||||
|
||||
'@puppeteer/browsers@2.10.4':
|
||||
dependencies:
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
extract-zip: 2.0.1
|
||||
progress: 2.0.3
|
||||
proxy-agent: 6.5.0
|
||||
semver: 7.7.1
|
||||
semver: 7.7.2
|
||||
tar-fs: 3.0.8
|
||||
yargs: 17.7.2
|
||||
transitivePeerDependencies:
|
||||
@ -5663,12 +5667,6 @@ snapshots:
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
tree-kill: 1.2.2
|
||||
|
||||
'@push.rocks/smartexpect@1.6.1':
|
||||
dependencies:
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
fast-deep-equal: 3.1.3
|
||||
|
||||
'@push.rocks/smartexpect@2.4.2':
|
||||
dependencies:
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
@ -5767,6 +5765,20 @@ snapshots:
|
||||
'@push.rocks/isounique': 1.0.5
|
||||
'@push.rocks/smartlog-interfaces': 3.0.2
|
||||
|
||||
'@push.rocks/smartlog@3.0.9':
|
||||
dependencies:
|
||||
'@api.global/typedrequest-interfaces': 3.0.19
|
||||
'@push.rocks/consolecolor': 2.0.2
|
||||
'@push.rocks/isounique': 1.0.5
|
||||
'@push.rocks/smartclickhouse': 2.0.17
|
||||
'@push.rocks/smartfile': 11.2.0
|
||||
'@push.rocks/smarthash': 3.0.4
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smarttime': 4.1.1
|
||||
'@push.rocks/webrequest': 3.0.37
|
||||
'@tsclass/tsclass': 9.2.0
|
||||
ora: 8.2.0
|
||||
|
||||
'@push.rocks/smartmanifest@2.0.2': {}
|
||||
|
||||
'@push.rocks/smartmarkdown@3.0.3':
|
||||
@ -5847,7 +5859,7 @@ snapshots:
|
||||
'@design.estate/dees-element': 2.0.42
|
||||
'@happy-dom/global-registrator': 15.11.7
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
fake-indexeddb: 6.0.0
|
||||
fake-indexeddb: 6.0.1
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- react
|
||||
@ -5965,7 +5977,7 @@ snapshots:
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartenv': 5.0.12
|
||||
'@push.rocks/smartjson': 5.0.20
|
||||
'@push.rocks/smartlog': 3.0.7
|
||||
'@push.rocks/smartlog': 3.0.9
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartrx': 3.0.10
|
||||
'@push.rocks/smarttime': 4.1.1
|
||||
@ -6049,7 +6061,7 @@ snapshots:
|
||||
'@push.rocks/smartversion@3.0.5':
|
||||
dependencies:
|
||||
'@types/semver': 7.7.0
|
||||
semver: 7.7.1
|
||||
semver: 7.7.2
|
||||
|
||||
'@push.rocks/smartxml@1.1.1':
|
||||
dependencies:
|
||||
@ -6061,38 +6073,6 @@ snapshots:
|
||||
'@types/js-yaml': 3.12.10
|
||||
js-yaml: 3.14.1
|
||||
|
||||
'@push.rocks/tapbundle@5.6.3(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)':
|
||||
dependencies:
|
||||
'@open-wc/testing': 4.0.0
|
||||
'@push.rocks/consolecolor': 2.0.2
|
||||
'@push.rocks/qenv': 6.1.0
|
||||
'@push.rocks/smartcrypto': 2.0.4
|
||||
'@push.rocks/smartdelay': 3.0.5
|
||||
'@push.rocks/smartenv': 5.0.12
|
||||
'@push.rocks/smartexpect': 1.6.1
|
||||
'@push.rocks/smartfile': 11.2.0
|
||||
'@push.rocks/smartjson': 5.0.20
|
||||
'@push.rocks/smartmongo': 2.0.12(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)
|
||||
'@push.rocks/smartpath': 5.0.18
|
||||
'@push.rocks/smartpromise': 4.2.3
|
||||
'@push.rocks/smartrequest': 2.1.0
|
||||
'@push.rocks/smarts3': 2.2.5
|
||||
'@push.rocks/smartshell': 3.2.3
|
||||
'@push.rocks/smarttime': 4.1.1
|
||||
expect: 29.7.0
|
||||
transitivePeerDependencies:
|
||||
- '@aws-sdk/credential-providers'
|
||||
- '@mongodb-js/zstd'
|
||||
- aws-crt
|
||||
- bufferutil
|
||||
- gcp-metadata
|
||||
- kerberos
|
||||
- mongodb-client-encryption
|
||||
- snappy
|
||||
- socks
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
'@push.rocks/tapbundle@6.0.3(@aws-sdk/credential-providers@3.804.0)(socks@2.8.4)':
|
||||
dependencies:
|
||||
'@open-wc/testing': 4.0.0
|
||||
@ -6718,14 +6698,14 @@ snapshots:
|
||||
|
||||
'@types/accepts@1.3.7':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/babel__code-frame@7.0.6': {}
|
||||
|
||||
'@types/body-parser@1.19.5':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/buffer-json@2.0.3': {}
|
||||
|
||||
@ -6741,17 +6721,17 @@ snapshots:
|
||||
|
||||
'@types/clean-css@4.2.11':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
source-map: 0.6.1
|
||||
|
||||
'@types/co-body@6.1.3':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
'@types/qs': 6.9.18
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/content-disposition@0.5.8': {}
|
||||
|
||||
@ -6762,11 +6742,11 @@ snapshots:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/express': 5.0.1
|
||||
'@types/keygrip': 1.0.6
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/cors@2.8.18':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/debounce@1.2.4': {}
|
||||
|
||||
@ -6780,7 +6760,7 @@ snapshots:
|
||||
|
||||
'@types/express-serve-static-core@5.0.6':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
'@types/qs': 6.9.18
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 0.17.4
|
||||
@ -6797,30 +6777,30 @@ snapshots:
|
||||
|
||||
'@types/from2@2.3.5':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/fs-extra@11.0.4':
|
||||
dependencies:
|
||||
'@types/jsonfile': 6.1.4
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/fs-extra@9.0.13':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/glob@7.2.0':
|
||||
dependencies:
|
||||
'@types/minimatch': 5.1.2
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/glob@8.1.0':
|
||||
dependencies:
|
||||
'@types/minimatch': 5.1.2
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/gunzip-maybe@1.4.2':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/hast@3.0.4':
|
||||
dependencies:
|
||||
@ -6854,7 +6834,7 @@ snapshots:
|
||||
|
||||
'@types/jsonfile@6.1.4':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/keygrip@1.0.6': {}
|
||||
|
||||
@ -6871,7 +6851,7 @@ snapshots:
|
||||
'@types/http-errors': 2.0.4
|
||||
'@types/keygrip': 1.0.6
|
||||
'@types/koa-compose': 3.2.8
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/mdast@4.0.4':
|
||||
dependencies:
|
||||
@ -6889,9 +6869,9 @@ snapshots:
|
||||
|
||||
'@types/node-forge@1.3.11':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/node@22.15.17':
|
||||
'@types/node@22.15.18':
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
@ -6909,19 +6889,19 @@ snapshots:
|
||||
|
||||
'@types/s3rver@3.7.4':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/semver@7.7.0': {}
|
||||
|
||||
'@types/send@0.17.4':
|
||||
dependencies:
|
||||
'@types/mime': 1.3.5
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/serve-static@1.15.7':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.4
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
'@types/send': 0.17.4
|
||||
|
||||
'@types/sinon-chai@3.2.12':
|
||||
@ -6941,11 +6921,11 @@ snapshots:
|
||||
|
||||
'@types/tar-stream@2.2.3':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/through2@2.0.41':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/triple-beam@1.3.5': {}
|
||||
|
||||
@ -6969,18 +6949,18 @@ snapshots:
|
||||
|
||||
'@types/whatwg-url@8.2.2':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
'@types/webidl-conversions': 7.0.3
|
||||
|
||||
'@types/which@3.0.4': {}
|
||||
|
||||
'@types/ws@7.4.7':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/ws@8.18.1':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
|
||||
'@types/yargs-parser@21.0.3': {}
|
||||
|
||||
@ -6990,7 +6970,7 @@ snapshots:
|
||||
|
||||
'@types/yauzl@2.10.3':
|
||||
dependencies:
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
optional: true
|
||||
|
||||
'@ungap/structured-clone@1.3.0': {}
|
||||
@ -7148,7 +7128,7 @@ snapshots:
|
||||
bare-events@2.5.4:
|
||||
optional: true
|
||||
|
||||
bare-fs@4.1.4:
|
||||
bare-fs@4.1.5:
|
||||
dependencies:
|
||||
bare-events: 2.5.4
|
||||
bare-path: 3.0.0
|
||||
@ -7258,7 +7238,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/http-cache-semantics': 4.0.4
|
||||
get-stream: 6.0.1
|
||||
http-cache-semantics: 4.1.1
|
||||
http-cache-semantics: 4.2.0
|
||||
keyv: 4.5.4
|
||||
mimic-response: 4.0.0
|
||||
normalize-url: 8.0.1
|
||||
@ -7495,6 +7475,10 @@ snapshots:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
debug@4.4.1:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
decode-named-character-reference@1.1.0:
|
||||
dependencies:
|
||||
character-entities: 2.0.2
|
||||
@ -7621,7 +7605,7 @@ snapshots:
|
||||
engine.io@6.6.4:
|
||||
dependencies:
|
||||
'@types/cors': 2.8.18
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
cookie: 0.7.2
|
||||
@ -7819,7 +7803,7 @@ snapshots:
|
||||
|
||||
extract-zip@2.0.1:
|
||||
dependencies:
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
get-stream: 5.2.0
|
||||
yauzl: 2.10.0
|
||||
optionalDependencies:
|
||||
@ -7829,7 +7813,7 @@ snapshots:
|
||||
|
||||
fake-indexeddb@5.0.2: {}
|
||||
|
||||
fake-indexeddb@6.0.0: {}
|
||||
fake-indexeddb@6.0.1: {}
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
|
||||
@ -8032,7 +8016,7 @@ snapshots:
|
||||
dependencies:
|
||||
basic-ftp: 5.0.5
|
||||
data-uri-to-buffer: 6.0.2
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -8182,7 +8166,7 @@ snapshots:
|
||||
deep-equal: 1.0.1
|
||||
http-errors: 1.8.1
|
||||
|
||||
http-cache-semantics@4.1.1: {}
|
||||
http-cache-semantics@4.2.0: {}
|
||||
|
||||
http-errors@1.6.3:
|
||||
dependencies:
|
||||
@ -8210,7 +8194,7 @@ snapshots:
|
||||
http-proxy-agent@7.0.2:
|
||||
dependencies:
|
||||
agent-base: 7.1.3
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -8341,8 +8325,6 @@ snapshots:
|
||||
|
||||
is-unicode-supported@1.3.0: {}
|
||||
|
||||
is-unicode-supported@2.0.0: {}
|
||||
|
||||
is-unicode-supported@2.1.0: {}
|
||||
|
||||
is-windows@1.0.2: {}
|
||||
@ -8415,7 +8397,7 @@ snapshots:
|
||||
jest-util@29.7.0:
|
||||
dependencies:
|
||||
'@jest/types': 29.6.3
|
||||
'@types/node': 22.15.17
|
||||
'@types/node': 22.15.18
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.9.0
|
||||
graceful-fs: 4.2.11
|
||||
@ -8523,7 +8505,7 @@ snapshots:
|
||||
|
||||
kuler@2.0.0: {}
|
||||
|
||||
lenis@1.3.1: {}
|
||||
lenis@1.3.3: {}
|
||||
|
||||
lines-and-columns@1.2.4: {}
|
||||
|
||||
@ -8967,7 +8949,7 @@ snapshots:
|
||||
micromark@4.0.2:
|
||||
dependencies:
|
||||
'@types/debug': 4.1.12
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
decode-named-character-reference: 1.1.0
|
||||
devlop: 1.1.0
|
||||
micromark-core-commonmark: 2.0.3
|
||||
@ -9196,7 +9178,7 @@ snapshots:
|
||||
cli-cursor: 5.0.0
|
||||
cli-spinners: 2.9.2
|
||||
is-interactive: 2.0.0
|
||||
is-unicode-supported: 2.0.0
|
||||
is-unicode-supported: 2.1.0
|
||||
log-symbols: 6.0.0
|
||||
stdin-discarder: 0.2.2
|
||||
string-width: 7.2.0
|
||||
@ -9233,7 +9215,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@tootallnate/quickjs-emscripten': 0.23.0
|
||||
agent-base: 7.1.3
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
get-uri: 6.0.4
|
||||
http-proxy-agent: 7.0.2
|
||||
https-proxy-agent: 7.0.6
|
||||
@ -9254,7 +9236,7 @@ snapshots:
|
||||
got: 12.6.1
|
||||
registry-auth-token: 5.1.0
|
||||
registry-url: 6.0.1
|
||||
semver: 7.7.1
|
||||
semver: 7.7.2
|
||||
|
||||
pako@0.2.9: {}
|
||||
|
||||
@ -9374,7 +9356,7 @@ snapshots:
|
||||
proxy-agent@6.5.0:
|
||||
dependencies:
|
||||
agent-base: 7.1.3
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
http-proxy-agent: 7.0.2
|
||||
https-proxy-agent: 7.0.6
|
||||
lru-cache: 7.18.3
|
||||
@ -9417,7 +9399,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@puppeteer/browsers': 2.10.4
|
||||
chromium-bidi: 5.1.0(devtools-protocol@0.0.1439962)
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
devtools-protocol: 0.0.1439962
|
||||
typed-query-selector: 2.12.0
|
||||
ws: 8.18.2
|
||||
@ -9643,6 +9625,8 @@ snapshots:
|
||||
|
||||
semver@7.7.1: {}
|
||||
|
||||
semver@7.7.2: {}
|
||||
|
||||
send@0.19.0:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
@ -9786,7 +9770,7 @@ snapshots:
|
||||
socks-proxy-agent@8.0.5:
|
||||
dependencies:
|
||||
agent-base: 7.1.3
|
||||
debug: 4.4.0
|
||||
debug: 4.4.1
|
||||
socks: 2.8.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -9917,7 +9901,7 @@ snapshots:
|
||||
pump: 3.0.2
|
||||
tar-stream: 3.1.7
|
||||
optionalDependencies:
|
||||
bare-fs: 4.1.4
|
||||
bare-fs: 4.1.5
|
||||
bare-path: 3.0.0
|
||||
transitivePeerDependencies:
|
||||
- bare-buffer
|
||||
|
74
readme.md
74
readme.md
@ -60,6 +60,78 @@ defaultLogger.log('warn', 'This is a warning message using the default logger');
|
||||
|
||||
This is particularly helpful for simple applications or for initial project setup.
|
||||
|
||||
### Interactive Console Features
|
||||
|
||||
Smartlog provides interactive console features through the `@push.rocks/smartlog/source-interactive` module:
|
||||
|
||||
#### Spinners
|
||||
|
||||
Use spinners to show progress for operations:
|
||||
|
||||
```typescript
|
||||
import { SmartlogSourceInteractive } from '@push.rocks/smartlog/source-interactive';
|
||||
|
||||
const spinner = new SmartlogSourceInteractive();
|
||||
spinner.text('Loading data...');
|
||||
|
||||
// Later, when the operation completes:
|
||||
spinner.finishSuccess('Data loaded successfully!');
|
||||
// Or if it fails:
|
||||
spinner.finishFail('Failed to load data');
|
||||
|
||||
// You can chain operations:
|
||||
spinner.text('Connecting to server');
|
||||
spinner.successAndNext('Fetching records');
|
||||
spinner.successAndNext('Processing data');
|
||||
spinner.finishSuccess('All done!');
|
||||
|
||||
// Customize appearance:
|
||||
spinner.setSpinnerStyle('line'); // 'dots', 'line', 'star', or 'simple'
|
||||
spinner.setColor('green'); // 'red', 'green', 'yellow', 'blue', etc.
|
||||
spinner.setSpeed(100); // Animation speed in milliseconds
|
||||
```
|
||||
|
||||
#### Progress Bars
|
||||
|
||||
Create progress bars for tracking operation progress:
|
||||
|
||||
```typescript
|
||||
import { SmartlogProgressBar } from '@push.rocks/smartlog/source-interactive';
|
||||
|
||||
const progressBar = new SmartlogProgressBar({
|
||||
total: 100, // Total number of items
|
||||
width: 40, // Width of the progress bar
|
||||
complete: '█', // Character for completed section
|
||||
incomplete: '░', // Character for incomplete section
|
||||
showEta: true, // Show estimated time remaining
|
||||
showPercent: true, // Show percentage
|
||||
showCount: true // Show count (e.g., "50/100")
|
||||
});
|
||||
|
||||
// Update progress
|
||||
progressBar.update(50); // Set to 50% progress
|
||||
|
||||
// Or increment
|
||||
progressBar.increment(10); // Increase by 10 units
|
||||
|
||||
// Change color
|
||||
progressBar.setColor('blue');
|
||||
|
||||
// Complete the progress bar
|
||||
progressBar.update(100); // or progressBar.complete();
|
||||
```
|
||||
|
||||
#### Non-Interactive Environments
|
||||
|
||||
Both spinners and progress bars automatically detect non-interactive environments (CI/CD, piped output, non-TTY) and provide fallback text-based output:
|
||||
|
||||
```
|
||||
[Loading] Loading data...
|
||||
Progress: 50% (50/100)
|
||||
Progress: 100% (100/100)
|
||||
[Success] Data loaded successfully!
|
||||
```
|
||||
|
||||
### Extending With Log Destinations
|
||||
|
||||
One of the core strengths of `@push.rocks/smartlog` is its ability to work with multiple log destinations, enabling you to log messages not just to the console but also to external logging services or custom destinations.
|
||||
@ -121,4 +193,4 @@ Registered at District court Bremen HRB 35230 HB, Germany
|
||||
|
||||
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||||
|
||||
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
||||
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
101
readme.plan.md
101
readme.plan.md
@ -0,0 +1,101 @@
|
||||
# Smartlog Interactive Console Features Plan
|
||||
|
||||
## Overview
|
||||
|
||||
This document outlines the plan for enhancing the console output capabilities of `@push.rocks/smartlog` by creating a comprehensive interactive console module. This involves renaming the current `ts_source_ora` module to `ts_source_interactive`, implementing our own spinner functionality (removing the ora dependency), and adding new features like progress bars and other interactive elements.
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### 1. Rename and Restructure
|
||||
|
||||
- Rename directory from `ts_source_ora` to `ts_source_interactive`
|
||||
- Update all imports, exports, and references
|
||||
- Update package.json exports to reflect new module name
|
||||
- Maintain backward compatibility through proper export paths
|
||||
|
||||
### 2. Custom Spinner Implementation
|
||||
|
||||
- Create a native spinner implementation to replace ora dependency
|
||||
- Implement spinner frames and animation timing
|
||||
- Maintain API compatibility with current spinner methods:
|
||||
- `text(textArg)` - Set text and start spinner
|
||||
- `stop()` - Stop the spinner
|
||||
- `finishSuccess(textArg?)` - Mark as succeeded
|
||||
- `finishFail(textArg?)` - Mark as failed
|
||||
- `successAndNext(textArg)` - Success and start new spinner
|
||||
- `failAndNext(textArg)` - Fail and start new spinner
|
||||
- Add spinner customization options (speed, frames, colors)
|
||||
|
||||
### 3. Progress Bar Implementation
|
||||
|
||||
- Create a progress bar component with the following features:
|
||||
- Configurable width and style
|
||||
- Percentage display
|
||||
- ETA calculation
|
||||
- Current/total value display
|
||||
- Custom formatting
|
||||
- Theming support
|
||||
- Methods for incrementing and updating
|
||||
|
||||
### 4. Additional Interactive Features
|
||||
|
||||
- Add indeterminate progress indicator
|
||||
- Add multi-line status display
|
||||
- Add table formatting for structured data
|
||||
- Add interactive prompts/confirmations
|
||||
|
||||
### 5. Testing
|
||||
|
||||
- Update existing tests to work with new implementation
|
||||
- Add tests for new progress bar functionality
|
||||
- Add tests for additional interactive features
|
||||
- Ensure consistent behavior across platforms
|
||||
|
||||
### 6. Documentation
|
||||
|
||||
- Update README with examples of new features
|
||||
- Add API documentation for all new methods
|
||||
- Include usage examples
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Progress Bar API
|
||||
|
||||
```typescript
|
||||
// Creating a progress bar
|
||||
const progressBar = new SmartlogProgressBar({
|
||||
total: 100,
|
||||
width: 40,
|
||||
complete: '=',
|
||||
incomplete: ' ',
|
||||
renderThrottle: 100, // ms
|
||||
clearOnComplete: false,
|
||||
showEta: true
|
||||
});
|
||||
|
||||
// Updating a progress bar
|
||||
progressBar.update(50); // Update to 50%
|
||||
progressBar.increment(10); // Increment by 10
|
||||
progressBar.complete(); // Mark as complete
|
||||
```
|
||||
|
||||
### Spinner API (maintains compatibility)
|
||||
|
||||
```typescript
|
||||
// Current API (to be maintained)
|
||||
const spinner = new SmartlogSourceInteractive();
|
||||
spinner.text('Loading data');
|
||||
spinner.finishSuccess('Data loaded successfully');
|
||||
|
||||
// New additions
|
||||
spinner.setSpinnerStyle('dots'); // Change spinner style
|
||||
spinner.setColor('green'); // Change color
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- Remove external dependency (ora) for better control and smaller bundle size
|
||||
- Provide more interactive console features for improved user experience
|
||||
- Maintain consistent API styling across all smartlog modules
|
||||
- Improve testability with custom implementation
|
||||
- Enable more advanced terminal interactions
|
64
test/test.noninteractive.node.ts
Normal file
64
test/test.noninteractive.node.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { expect, tap } from '@push.rocks/tapbundle';
|
||||
import { SmartlogSourceInteractive, SmartlogProgressBar } from '../ts_source_interactive/index.js';
|
||||
|
||||
// Test instances
|
||||
let testSpinner: SmartlogSourceInteractive;
|
||||
let testProgressBar: SmartlogProgressBar;
|
||||
|
||||
// Original state for restoration
|
||||
const originalState = {
|
||||
stdoutTTY: process.stdout.isTTY,
|
||||
consoleLog: console.log
|
||||
};
|
||||
|
||||
// Log tracking
|
||||
const logs: string[] = [];
|
||||
|
||||
tap.test('should handle non-interactive mode correctly', async (toolsArg) => {
|
||||
// Setup non-interactive mode
|
||||
process.stdout.isTTY = false;
|
||||
console.log = (...args: any[]) => {
|
||||
logs.push(args.join(' '));
|
||||
};
|
||||
|
||||
// Test spinner creation
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
expect(testSpinner).toBeTruthy();
|
||||
|
||||
// Test spinner text
|
||||
logs.length = 0;
|
||||
testSpinner.text('Loading data');
|
||||
expect(logs.length).toBeGreaterThan(0);
|
||||
expect(logs[0]).toContain('[Loading]');
|
||||
expect(logs[0]).toContain('Loading data');
|
||||
|
||||
// Test spinner success
|
||||
logs.length = 0;
|
||||
testSpinner.finishSuccess('Task completed');
|
||||
expect(logs.length).toBeGreaterThan(0);
|
||||
expect(logs[0]).toContain('[Success]');
|
||||
expect(logs[0]).toContain('Task completed');
|
||||
|
||||
// Test progress bar
|
||||
testProgressBar = new SmartlogProgressBar({ total: 100 });
|
||||
expect(testProgressBar).toBeTruthy();
|
||||
|
||||
// Test progress updates
|
||||
logs.length = 0;
|
||||
testProgressBar.update(10);
|
||||
testProgressBar.update(50);
|
||||
testProgressBar.update(100);
|
||||
|
||||
expect(logs.length).toBeGreaterThan(0);
|
||||
const progressLogs = logs.join(' ');
|
||||
expect(progressLogs).toContain('10%');
|
||||
expect(progressLogs).toContain('50%');
|
||||
expect(progressLogs).toContain('100%');
|
||||
|
||||
// Cleanup
|
||||
testSpinner.stop();
|
||||
console.log = originalState.consoleLog;
|
||||
process.stdout.isTTY = originalState.stdoutTTY;
|
||||
});
|
||||
|
||||
export default tap.start();
|
190
test/test.source-interactive.node.ts
Normal file
190
test/test.source-interactive.node.ts
Normal file
@ -0,0 +1,190 @@
|
||||
import { expect, tap } from '@push.rocks/tapbundle';
|
||||
import { SmartlogSourceInteractive, SmartlogProgressBar, SmartlogSourceOra } from '../ts_source_interactive/index.js';
|
||||
|
||||
// Test spinner functionality
|
||||
let testSpinner: SmartlogSourceInteractive;
|
||||
|
||||
// Helper function to clean up spinners after each test
|
||||
const cleanupSpinner = (spinner: SmartlogSourceInteractive) => {
|
||||
if (spinner.isStarted()) {
|
||||
spinner.stop();
|
||||
}
|
||||
};
|
||||
|
||||
tap.test('should create a SmartlogSourceInteractive instance', async () => {
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
testSpinner.setSpeed(10); // Set fast animation speed for tests
|
||||
expect(testSpinner).toBeTruthy();
|
||||
expect(testSpinner.isStarted()).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should set text and start spinner', async () => {
|
||||
const testText = 'Testing spinner';
|
||||
testSpinner.text(testText);
|
||||
|
||||
expect(testSpinner.isStarted()).toBeTrue();
|
||||
cleanupSpinner(testSpinner);
|
||||
});
|
||||
|
||||
tap.test('should update text', async () => {
|
||||
const newText = 'Updated text';
|
||||
testSpinner.text(newText);
|
||||
|
||||
expect(testSpinner.isStarted()).toBeTrue();
|
||||
cleanupSpinner(testSpinner);
|
||||
});
|
||||
|
||||
tap.test('should stop spinner', async () => {
|
||||
testSpinner.stop();
|
||||
// We can't easily test the visual state, but we can verify it doesn't throw errors
|
||||
});
|
||||
|
||||
tap.test('should finish with success', async () => {
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
testSpinner.text('Starting again');
|
||||
|
||||
const successText = 'Operation successful';
|
||||
testSpinner.finishSuccess(successText);
|
||||
|
||||
expect(testSpinner.isStarted()).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should finish with failure', async () => {
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
testSpinner.text('Starting again');
|
||||
|
||||
const failText = 'Operation failed';
|
||||
testSpinner.finishFail(failText);
|
||||
|
||||
expect(testSpinner.isStarted()).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should handle success and next', async () => {
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
testSpinner.setSpeed(10); // Fast animation
|
||||
testSpinner.text('Starting again');
|
||||
|
||||
const nextText = 'Next operation';
|
||||
testSpinner.successAndNext(nextText);
|
||||
|
||||
expect(testSpinner.isStarted()).toBeTrue();
|
||||
cleanupSpinner(testSpinner);
|
||||
});
|
||||
|
||||
tap.test('should handle fail and next', async () => {
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
testSpinner.setSpeed(10); // Fast animation
|
||||
testSpinner.text('Starting again');
|
||||
|
||||
const nextText = 'Next operation after failure';
|
||||
testSpinner.failAndNext(nextText);
|
||||
|
||||
expect(testSpinner.isStarted()).toBeTrue();
|
||||
cleanupSpinner(testSpinner);
|
||||
});
|
||||
|
||||
tap.test('should set spinner style', async () => {
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
testSpinner.setSpeed(10); // Fast animation
|
||||
testSpinner.setSpinnerStyle('line');
|
||||
testSpinner.text('Custom style spinner');
|
||||
|
||||
// Visual effect can't be easily tested, but we can verify it doesn't throw errors
|
||||
expect(testSpinner.isStarted()).toBeTrue();
|
||||
cleanupSpinner(testSpinner);
|
||||
});
|
||||
|
||||
tap.test('should set spinner color', async () => {
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
testSpinner.setSpeed(10); // Fast animation
|
||||
testSpinner.setColor('green');
|
||||
testSpinner.text('Green spinner');
|
||||
|
||||
// Visual effect can't be easily tested, but we can verify it doesn't throw errors
|
||||
expect(testSpinner.isStarted()).toBeTrue();
|
||||
cleanupSpinner(testSpinner);
|
||||
});
|
||||
|
||||
tap.test('should set animation speed', async () => {
|
||||
testSpinner = new SmartlogSourceInteractive();
|
||||
testSpinner.setSpeed(10); // Actually set fast for testing
|
||||
testSpinner.text('Slow spinner');
|
||||
|
||||
// Visual effect can't be easily tested, but we can verify it doesn't throw errors
|
||||
expect(testSpinner.isStarted()).toBeTrue();
|
||||
cleanupSpinner(testSpinner);
|
||||
});
|
||||
|
||||
// Test progress bar functionality
|
||||
let testProgressBar: SmartlogProgressBar;
|
||||
|
||||
tap.test('should create a progress bar instance', async () => {
|
||||
testProgressBar = new SmartlogProgressBar({
|
||||
total: 100
|
||||
});
|
||||
|
||||
expect(testProgressBar).toBeTruthy();
|
||||
});
|
||||
|
||||
tap.test('should update progress bar value', async () => {
|
||||
testProgressBar.update(50);
|
||||
// Visual effect can't be easily tested, but we can verify it doesn't throw errors
|
||||
});
|
||||
|
||||
tap.test('should increment progress bar', async () => {
|
||||
const initialValue = 50;
|
||||
const increment = 10;
|
||||
testProgressBar = new SmartlogProgressBar({ total: 100 });
|
||||
testProgressBar.update(initialValue);
|
||||
testProgressBar.increment(increment);
|
||||
// Visual effect can't be easily tested, but we can verify it doesn't throw errors
|
||||
});
|
||||
|
||||
tap.test('should complete progress bar', async () => {
|
||||
testProgressBar = new SmartlogProgressBar({ total: 100 });
|
||||
testProgressBar.update(50);
|
||||
testProgressBar.update(100); // Update to 100% to simulate completion
|
||||
// Visual effect can't be easily tested, but we can verify it doesn't throw errors
|
||||
});
|
||||
|
||||
tap.test('should set progress bar color', async () => {
|
||||
testProgressBar = new SmartlogProgressBar({ total: 100 });
|
||||
testProgressBar.setColor('blue');
|
||||
testProgressBar.update(50);
|
||||
// Visual effect can't be easily tested, but we can verify it doesn't throw errors
|
||||
});
|
||||
|
||||
tap.test('should handle custom progress bar options', async () => {
|
||||
testProgressBar = new SmartlogProgressBar({
|
||||
total: 100,
|
||||
width: 40,
|
||||
complete: '=',
|
||||
incomplete: '-',
|
||||
showEta: false,
|
||||
showPercent: true,
|
||||
showCount: true
|
||||
});
|
||||
|
||||
testProgressBar.update(30);
|
||||
// Visual effect can't be easily tested, but we can verify it doesn't throw errors
|
||||
});
|
||||
|
||||
// Test backward compatibility with SmartlogSourceOra
|
||||
let testSourceOra: SmartlogSourceOra;
|
||||
|
||||
tap.test('should create a SmartlogSourceOra instance for backward compatibility', async () => {
|
||||
testSourceOra = new SmartlogSourceOra();
|
||||
expect(testSourceOra).toBeTruthy();
|
||||
expect(testSourceOra.isStarted()).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should maintain compatibility with old API', async () => {
|
||||
testSourceOra.setSpeed(10); // Fast animation
|
||||
testSourceOra.text('Testing backward compatibility');
|
||||
expect(testSourceOra.isStarted()).toBeTrue();
|
||||
|
||||
testSourceOra.finishSuccess('Success');
|
||||
expect(testSourceOra.isStarted()).toBeFalse();
|
||||
});
|
||||
|
||||
export default tap.start();
|
@ -1,75 +0,0 @@
|
||||
import { expect, tap } from '@push.rocks/tapbundle';
|
||||
import { SmartlogSourceOra } from '../ts_source_ora/index.js';
|
||||
|
||||
let testSourceOra: SmartlogSourceOra;
|
||||
|
||||
tap.test('should create a SmartlogSourceOra instance', async () => {
|
||||
testSourceOra = new SmartlogSourceOra();
|
||||
expect(testSourceOra).toBeTruthy();
|
||||
expect(testSourceOra.started).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should set text and start spinner', async () => {
|
||||
const testText = 'Testing ora spinner';
|
||||
testSourceOra.text(testText);
|
||||
|
||||
expect(testSourceOra.started).toBeTrue();
|
||||
expect(testSourceOra.oraInstance.text).toEqual(testText);
|
||||
});
|
||||
|
||||
tap.test('should update text', async () => {
|
||||
const newText = 'Updated text';
|
||||
testSourceOra.text(newText);
|
||||
|
||||
expect(testSourceOra.oraInstance.text).toEqual(newText);
|
||||
expect(testSourceOra.started).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('should stop spinner', async () => {
|
||||
testSourceOra.stop();
|
||||
// We can't easily test the visual state, but we can verify it doesn't throw errors
|
||||
});
|
||||
|
||||
tap.test('should finish with success', async () => {
|
||||
testSourceOra = new SmartlogSourceOra();
|
||||
testSourceOra.text('Starting again');
|
||||
|
||||
const successText = 'Operation successful';
|
||||
testSourceOra.finishSuccess(successText);
|
||||
|
||||
expect(testSourceOra.started).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should finish with failure', async () => {
|
||||
testSourceOra = new SmartlogSourceOra();
|
||||
testSourceOra.text('Starting again');
|
||||
|
||||
const failText = 'Operation failed';
|
||||
testSourceOra.finishFail(failText);
|
||||
|
||||
expect(testSourceOra.started).toBeFalse();
|
||||
});
|
||||
|
||||
tap.test('should handle success and next', async () => {
|
||||
testSourceOra = new SmartlogSourceOra();
|
||||
testSourceOra.text('Starting again');
|
||||
|
||||
const nextText = 'Next operation';
|
||||
testSourceOra.successAndNext(nextText);
|
||||
|
||||
expect(testSourceOra.started).toBeTrue();
|
||||
expect(testSourceOra.oraInstance.text).toEqual(nextText);
|
||||
});
|
||||
|
||||
tap.test('should handle fail and next', async () => {
|
||||
testSourceOra = new SmartlogSourceOra();
|
||||
testSourceOra.text('Starting again');
|
||||
|
||||
const nextText = 'Next operation after failure';
|
||||
testSourceOra.failAndNext(nextText);
|
||||
|
||||
expect(testSourceOra.started).toBeTrue();
|
||||
expect(testSourceOra.oraInstance.text).toEqual(nextText);
|
||||
});
|
||||
|
||||
export default tap.start();
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartlog',
|
||||
version: '3.0.9',
|
||||
version: '3.1.0',
|
||||
description: 'A minimalistic, distributed, and extensible logging tool supporting centralized log management.'
|
||||
}
|
||||
|
415
ts_source_interactive/index.ts
Normal file
415
ts_source_interactive/index.ts
Normal file
@ -0,0 +1,415 @@
|
||||
import * as plugins from './smartlog-source-interactive.plugins.js';
|
||||
|
||||
/**
|
||||
* Utility to detect if the environment is interactive
|
||||
* Checks for TTY capability and common CI environment variables
|
||||
*/
|
||||
const isInteractive = () => {
|
||||
try {
|
||||
return Boolean(
|
||||
// Check TTY capability
|
||||
process.stdout && process.stdout.isTTY &&
|
||||
|
||||
// Additional checks for non-interactive environments
|
||||
!('CI' in process.env) &&
|
||||
!process.env.GITHUB_ACTIONS &&
|
||||
!process.env.JENKINS_URL &&
|
||||
!process.env.GITLAB_CI &&
|
||||
!process.env.TRAVIS &&
|
||||
!process.env.CIRCLECI &&
|
||||
process.env.TERM !== 'dumb'
|
||||
);
|
||||
} catch (e) {
|
||||
// If any error occurs (e.g., in browser environments without process),
|
||||
// assume a non-interactive environment to be safe
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Helper to log messages in non-interactive mode
|
||||
const logMessage = (message: string, prefix = '') => {
|
||||
if (prefix) {
|
||||
console.log(`${prefix} ${message}`);
|
||||
} else {
|
||||
console.log(message);
|
||||
}
|
||||
};
|
||||
|
||||
// Spinner frames and styles
|
||||
const spinnerFrames = {
|
||||
dots: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],
|
||||
line: ['|', '/', '-', '\\'],
|
||||
star: ['✶', '✸', '✹', '✺', '✹', '✷'],
|
||||
simple: ['-', '\\', '|', '/']
|
||||
};
|
||||
|
||||
// Color names mapping to ANSI color codes
|
||||
const colors = {
|
||||
black: '\u001b[30m',
|
||||
red: '\u001b[31m',
|
||||
green: '\u001b[32m',
|
||||
yellow: '\u001b[33m',
|
||||
blue: '\u001b[34m',
|
||||
magenta: '\u001b[35m',
|
||||
cyan: '\u001b[36m',
|
||||
white: '\u001b[37m',
|
||||
gray: '\u001b[90m',
|
||||
reset: '\u001b[0m'
|
||||
};
|
||||
|
||||
/**
|
||||
* A class for creating interactive spinners
|
||||
* Automatically handles non-interactive environments
|
||||
*/
|
||||
export class SmartlogSourceInteractive {
|
||||
private textContent: string = 'loading';
|
||||
private currentFrame: number = 0;
|
||||
private interval: NodeJS.Timeout | null = null;
|
||||
private started: boolean = false;
|
||||
private spinnerStyle: keyof typeof spinnerFrames = 'dots';
|
||||
private color: keyof typeof colors = 'cyan';
|
||||
private frames: string[];
|
||||
private frameInterval: number = 80;
|
||||
private interactive: boolean;
|
||||
|
||||
constructor() {
|
||||
this.frames = spinnerFrames[this.spinnerStyle];
|
||||
this.interactive = isInteractive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text for the spinner and starts it if not already started
|
||||
*/
|
||||
public text(textArg: string) {
|
||||
this.textContent = textArg;
|
||||
|
||||
if (!this.interactive) {
|
||||
// In non-interactive mode, just log the message with a loading indicator
|
||||
logMessage(textArg, '[Loading]');
|
||||
this.started = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.started) {
|
||||
this.started = true;
|
||||
this.start();
|
||||
} else {
|
||||
this.renderFrame();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the spinner animation
|
||||
*/
|
||||
private start() {
|
||||
if (!this.interactive) {
|
||||
return; // No animation in non-interactive mode
|
||||
}
|
||||
|
||||
if (this.interval) {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
|
||||
this.renderFrame();
|
||||
this.interval = setInterval(() => {
|
||||
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
||||
this.renderFrame();
|
||||
}, this.frameInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the current frame of the spinner
|
||||
*/
|
||||
private renderFrame() {
|
||||
if (!this.started || !this.interactive) return;
|
||||
|
||||
const frame = this.frames[this.currentFrame];
|
||||
const colorCode = colors[this.color];
|
||||
const resetCode = colors.reset;
|
||||
|
||||
// Only use ANSI escape codes in interactive mode
|
||||
process.stdout.write('\r\x1b[2K'); // Clear the current line
|
||||
process.stdout.write(`${colorCode}${frame}${resetCode} ${this.textContent}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the spinner
|
||||
*/
|
||||
public stop() {
|
||||
// Always clear the interval even in non-interactive mode
|
||||
// This prevents memory leaks in tests and long-running applications
|
||||
if (this.interval) {
|
||||
clearInterval(this.interval);
|
||||
this.interval = null;
|
||||
}
|
||||
|
||||
if (!this.interactive) {
|
||||
return; // No need to clear the line in non-interactive mode
|
||||
}
|
||||
|
||||
process.stdout.write('\r\x1b[2K'); // Clear the current line
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the spinner as successful and optionally displays a success message
|
||||
*/
|
||||
public finishSuccess(textArg?: string) {
|
||||
const message = textArg || this.textContent;
|
||||
|
||||
// Always stop the spinner first to clean up intervals
|
||||
this.stop();
|
||||
|
||||
if (!this.interactive) {
|
||||
logMessage(message, '[Success]');
|
||||
} else {
|
||||
const successSymbol = colors.green + '✓' + colors.reset;
|
||||
process.stdout.write(`${successSymbol} ${message}\n`);
|
||||
}
|
||||
|
||||
this.started = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the spinner as failed and optionally displays a failure message
|
||||
*/
|
||||
public finishFail(textArg?: string) {
|
||||
const message = textArg || this.textContent;
|
||||
|
||||
// Always stop the spinner first to clean up intervals
|
||||
this.stop();
|
||||
|
||||
if (!this.interactive) {
|
||||
logMessage(message, '[Failed]');
|
||||
} else {
|
||||
const failSymbol = colors.red + '✗' + colors.reset;
|
||||
process.stdout.write(`${failSymbol} ${message}\n`);
|
||||
}
|
||||
|
||||
this.started = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the current spinner as successful and starts a new one
|
||||
*/
|
||||
public successAndNext(textArg: string) {
|
||||
this.finishSuccess();
|
||||
this.text(textArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the current spinner as failed and starts a new one
|
||||
*/
|
||||
public failAndNext(textArg: string) {
|
||||
this.finishFail();
|
||||
this.text(textArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the spinner style
|
||||
*/
|
||||
public setSpinnerStyle(style: keyof typeof spinnerFrames) {
|
||||
this.spinnerStyle = style;
|
||||
this.frames = spinnerFrames[style];
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the spinner color
|
||||
*/
|
||||
public setColor(colorName: keyof typeof colors) {
|
||||
if (colorName in colors) {
|
||||
this.color = colorName;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the animation speed in milliseconds
|
||||
*/
|
||||
public setSpeed(ms: number) {
|
||||
this.frameInterval = ms;
|
||||
if (this.started) {
|
||||
this.stop();
|
||||
this.start();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current started state
|
||||
*/
|
||||
public isStarted() {
|
||||
return this.started;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IProgressBarOptions {
|
||||
total: number;
|
||||
width?: number;
|
||||
complete?: string;
|
||||
incomplete?: string;
|
||||
renderThrottle?: number;
|
||||
clear?: boolean;
|
||||
showEta?: boolean;
|
||||
showPercent?: boolean;
|
||||
showCount?: boolean;
|
||||
}
|
||||
|
||||
export class SmartlogProgressBar {
|
||||
private total: number;
|
||||
private current: number = 0;
|
||||
private width: number;
|
||||
private complete: string;
|
||||
private incomplete: string;
|
||||
private renderThrottle: number;
|
||||
private clear: boolean;
|
||||
private showEta: boolean;
|
||||
private showPercent: boolean;
|
||||
private showCount: boolean;
|
||||
private color: keyof typeof colors = 'green';
|
||||
private startTime: number | null = null;
|
||||
private lastRenderTime: number = 0;
|
||||
private interactive: boolean;
|
||||
private lastLoggedPercent: number = 0;
|
||||
private logThreshold: number = 10; // Log every 10% in non-interactive mode
|
||||
|
||||
constructor(options: IProgressBarOptions) {
|
||||
this.total = options.total;
|
||||
this.width = options.width || 30;
|
||||
this.complete = options.complete || '█';
|
||||
this.incomplete = options.incomplete || '░';
|
||||
this.renderThrottle = options.renderThrottle || 16;
|
||||
this.clear = options.clear !== undefined ? options.clear : false;
|
||||
this.showEta = options.showEta !== undefined ? options.showEta : true;
|
||||
this.showPercent = options.showPercent !== undefined ? options.showPercent : true;
|
||||
this.showCount = options.showCount !== undefined ? options.showCount : true;
|
||||
this.interactive = isInteractive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the progress bar to a specific value
|
||||
*/
|
||||
public update(value: number): this {
|
||||
if (this.startTime === null) {
|
||||
this.startTime = Date.now();
|
||||
}
|
||||
|
||||
this.current = Math.min(value, this.total);
|
||||
|
||||
if (!this.interactive) {
|
||||
// In non-interactive mode, log progress at certain thresholds
|
||||
const percent = Math.floor((this.current / this.total) * 100);
|
||||
const currentThreshold = Math.floor(percent / this.logThreshold) * this.logThreshold;
|
||||
|
||||
if (currentThreshold > this.lastLoggedPercent || percent === 100) {
|
||||
this.lastLoggedPercent = currentThreshold;
|
||||
logMessage(`Progress: ${percent}% (${this.current}/${this.total})`);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Throttle rendering to avoid excessive updates in interactive mode
|
||||
const now = Date.now();
|
||||
if (now - this.lastRenderTime < this.renderThrottle) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastRenderTime = now;
|
||||
this.render();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the progress bar by a value
|
||||
*/
|
||||
public increment(value: number = 1): this {
|
||||
return this.update(this.current + value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the progress bar as complete
|
||||
*/
|
||||
public complete(): this {
|
||||
this.update(this.total);
|
||||
|
||||
if (!this.interactive) {
|
||||
logMessage(`Completed: 100% (${this.total}/${this.total})`);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.clear) {
|
||||
process.stdout.write('\r\x1b[2K');
|
||||
} else {
|
||||
process.stdout.write('\n');
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color of the progress bar
|
||||
*/
|
||||
public setColor(colorName: keyof typeof colors): this {
|
||||
if (colorName in colors) {
|
||||
this.color = colorName;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the progress bar
|
||||
*/
|
||||
private render(): void {
|
||||
if (!this.interactive) {
|
||||
return; // Don't render in non-interactive mode
|
||||
}
|
||||
|
||||
// Calculate percent complete
|
||||
const percent = Math.floor((this.current / this.total) * 100);
|
||||
const completeLength = Math.round((this.current / this.total) * this.width);
|
||||
const incompleteLength = this.width - completeLength;
|
||||
|
||||
// Build the progress bar
|
||||
const completePart = colors[this.color] + this.complete.repeat(completeLength) + colors.reset;
|
||||
const incompletePart = this.incomplete.repeat(incompleteLength);
|
||||
const progressBar = `[${completePart}${incompletePart}]`;
|
||||
|
||||
// Calculate ETA if needed
|
||||
let etaStr = '';
|
||||
if (this.showEta && this.startTime !== null && this.current > 0) {
|
||||
const elapsed = (Date.now() - this.startTime) / 1000;
|
||||
const rate = this.current / elapsed;
|
||||
const remaining = Math.max(0, this.total - this.current);
|
||||
const eta = Math.round(remaining / rate);
|
||||
|
||||
const mins = Math.floor(eta / 60);
|
||||
const secs = eta % 60;
|
||||
etaStr = ` eta: ${mins}m${secs}s`;
|
||||
}
|
||||
|
||||
// Build additional information
|
||||
const percentStr = this.showPercent ? ` ${percent}%` : '';
|
||||
const countStr = this.showCount ? ` ${this.current}/${this.total}` : '';
|
||||
|
||||
// Clear the line and render
|
||||
process.stdout.write('\r\x1b[2K');
|
||||
process.stdout.write(`${progressBar}${percentStr}${countStr}${etaStr}`);
|
||||
}
|
||||
}
|
||||
|
||||
// For backward compatibility with 'source-ora' module
|
||||
export class SmartlogSourceOra extends SmartlogSourceInteractive {
|
||||
// Add a stub for the oraInstance property for backward compatibility
|
||||
public get oraInstance() {
|
||||
return {
|
||||
text: this.textContent,
|
||||
start: () => this.start(),
|
||||
stop: () => this.stop(),
|
||||
succeed: (text?: string) => this.finishSuccess(text),
|
||||
fail: (text?: string) => this.finishFail(text)
|
||||
};
|
||||
}
|
||||
|
||||
public set oraInstance(value: any) {
|
||||
// No-op, just for compatibility
|
||||
}
|
||||
}
|
10
ts_source_interactive/smartlog-source-interactive.plugins.ts
Normal file
10
ts_source_interactive/smartlog-source-interactive.plugins.ts
Normal file
@ -0,0 +1,10 @@
|
||||
// pushrocks scope
|
||||
import * as smartlogInterfaces from '../dist_ts_interfaces/index.js';
|
||||
import * as consolecolor from '@push.rocks/consolecolor';
|
||||
|
||||
export { smartlogInterfaces, consolecolor };
|
||||
|
||||
// node.js internal
|
||||
import { stdout, stderr } from 'process';
|
||||
|
||||
export { stdout, stderr };
|
@ -1,40 +0,0 @@
|
||||
import * as plugins from './smartlog-source-ora.plugins.js';
|
||||
|
||||
export class SmartlogSourceOra {
|
||||
public oraInstance = plugins.ora('loading');
|
||||
public started = false;
|
||||
|
||||
constructor() {}
|
||||
|
||||
public text(textArg: string) {
|
||||
this.oraInstance.text = textArg;
|
||||
if (!this.started) {
|
||||
this.started = true;
|
||||
this.oraInstance.start();
|
||||
}
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.oraInstance.stop();
|
||||
}
|
||||
|
||||
public finishSuccess(textArg?: string) {
|
||||
this.oraInstance.succeed(textArg);
|
||||
this.started = false;
|
||||
}
|
||||
|
||||
public finishFail(textArg?: string) {
|
||||
this.oraInstance.fail(textArg);
|
||||
this.started = false;
|
||||
}
|
||||
|
||||
public successAndNext(textArg: string) {
|
||||
this.finishSuccess();
|
||||
this.text(textArg);
|
||||
}
|
||||
|
||||
public failAndNext(textArg: string) {
|
||||
this.finishFail();
|
||||
this.text(textArg);
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
// pushrocks scope
|
||||
import * as smartlogInterfaces from '../dist_ts_interfaces/index.js';
|
||||
|
||||
export { smartlogInterfaces };
|
||||
|
||||
// third party scope
|
||||
import ora from 'ora';
|
||||
|
||||
export { ora };
|
Loading…
x
Reference in New Issue
Block a user