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
|
||||
|
72
readme.md
72
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.
|
||||
|
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