diff --git a/.changeset/shaggy-bugs-wave.md b/.changeset/shaggy-bugs-wave.md new file mode 100644 index 000000000..b9e59c2bf --- /dev/null +++ b/.changeset/shaggy-bugs-wave.md @@ -0,0 +1,5 @@ +--- +"@workflow/cli": patch +--- + +Show info notice when a newer version is available diff --git a/.changeset/violet-bats-crash.md b/.changeset/violet-bats-crash.md new file mode 100644 index 000000000..40dfad6b9 --- /dev/null +++ b/.changeset/violet-bats-crash.md @@ -0,0 +1,5 @@ +--- +"@workflow/cli": patch +--- + +Add -i / --interactive flag for enabling pagination bindings, new default being off diff --git a/packages/cli/package.json b/packages/cli/package.json index d2d51e4ca..29997c7ea 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -31,9 +31,14 @@ "dirname": "workflow", "commands": "./dist/commands", "plugins": [ - "@oclif/plugin-help" + "@oclif/plugin-help", + "@oclif/plugin-warn-if-update-available" ], - "topicSeparator": " " + "topicSeparator": " ", + "warn-if-update-available": { + "timeoutInDays": 7, + "message": "<%= config.name %> update available from <%= chalk.greenBright(config.version) %> to <%= chalk.greenBright(latest) %>. Run \"npm install <%= config.name %>@latest\" to update." + } }, "devDependencies": { "@types/node": "catalog:", @@ -42,6 +47,7 @@ "dependencies": { "@oclif/core": "4.0.0", "@oclif/plugin-help": "6.2.31", + "@oclif/plugin-warn-if-update-available": "3.1.53", "@swc/core": "catalog:", "@workflow/builders": "workspace:*", "@workflow/swc-plugin": "workspace:*", diff --git a/packages/cli/src/commands/inspect.ts b/packages/cli/src/commands/inspect.ts index 54d13ed64..159d053d9 100644 --- a/packages/cli/src/commands/inspect.ts +++ b/packages/cli/src/commands/inspect.ts @@ -239,6 +239,7 @@ function toInspectOptions(flags: any): InspectCLIOptions { workflowName: flags.workflowName, withData: flags.withData, backend: flags.backend, + interactive: flags.interactive, }; } diff --git a/packages/cli/src/lib/config/types.ts b/packages/cli/src/lib/config/types.ts index 2e818e738..83f7c0442 100644 --- a/packages/cli/src/lib/config/types.ts +++ b/packages/cli/src/lib/config/types.ts @@ -21,4 +21,5 @@ export type InspectCLIOptions = { withData?: boolean; backend?: string; disableRelativeDates?: boolean; + interactive?: boolean; }; diff --git a/packages/cli/src/lib/inspect/flags.ts b/packages/cli/src/lib/inspect/flags.ts index 0d84d28ac..1757c4fbf 100644 --- a/packages/cli/src/lib/inspect/flags.ts +++ b/packages/cli/src/lib/inspect/flags.ts @@ -127,4 +127,12 @@ export const cliFlags = { helpLabel: '--limit', helpValue: 'NUMBER', }), + interactive: Flags.boolean({ + description: 'Enable interactive pagination with keyboard controls', + required: false, + char: 'i', + default: false, + helpGroup: 'Output', + helpLabel: '-i, --interactive', + }), }; diff --git a/packages/cli/src/lib/inspect/output.ts b/packages/cli/src/lib/inspect/output.ts index e41540748..75700d15f 100644 --- a/packages/cli/src/lib/inspect/output.ts +++ b/packages/cli/src/lib/inspect/output.ts @@ -543,6 +543,7 @@ export const listRuns = async (world: World, opts: InspectCLIOptions = {}) => { await setupListPagination({ initialCursor: opts.cursor, + interactive: opts.interactive, fetchPage: async (cursor) => { try { const runs = await world.runs.list({ @@ -680,6 +681,7 @@ export const listSteps = async ( await setupListPagination({ initialCursor: opts.cursor, + interactive: opts.interactive, fetchPage: async (cursor) => { logger.debug(`Fetching steps for run ${runId}`); try { @@ -888,6 +890,7 @@ export const listEvents = async ( await setupListPagination({ initialCursor: opts.cursor, + interactive: opts.interactive, fetchPage: async (cursor) => { logger.debug(`Fetching events for run ${filterId}`); try { @@ -957,6 +960,7 @@ export const listHooks = async (world: World, opts: InspectCLIOptions = {}) => { // Setup pagination with new mechanism await setupListPagination({ initialCursor: opts.cursor, + interactive: opts.interactive, fetchPage: async (cursor) => { if (!runId) { logger.debug('Fetching all hooks'); diff --git a/packages/cli/src/lib/inspect/pagination.ts b/packages/cli/src/lib/inspect/pagination.ts index 3c2838a59..89c04299b 100644 --- a/packages/cli/src/lib/inspect/pagination.ts +++ b/packages/cli/src/lib/inspect/pagination.ts @@ -143,6 +143,11 @@ export interface ListPaginationOptions { * Optional callback for when fetching starts */ onFetchStart?: (pageIndex: number) => void; + + /** + * Enable interactive pagination with keyboard controls + */ + interactive?: boolean; } /** @@ -151,7 +156,11 @@ export interface ListPaginationOptions { export async function setupListPagination( options: ListPaginationOptions ): Promise { - const { initialCursor, fetchPage, displayPage, onFetchStart } = options; + const { initialCursor, fetchPage, displayPage, onFetchStart, interactive } = + options; + + // Interactive mode requires both TTY support and explicit --interactive flag + const enableInteractive = interactive && isInteractive(); // Pages stack - stores all fetched pages const pages: PageData[] = []; @@ -172,7 +181,7 @@ export async function setupListPagination( pageIndex = index; // Clear screen for subsequent pages in interactive mode - if (isInteractive()) { + if (enableInteractive) { console.clear(); } @@ -183,7 +192,13 @@ export async function setupListPagination( // Fetch and display first page const firstPage = await showPage(0, initialCursor); - if (!isInteractive()) { + // In non-interactive mode, show info if there are more pages + if (!enableInteractive) { + if (firstPage.hasMore) { + logger.info( + '\nMore results available. Use --interactive (-i) to paginate through results.' + ); + } return; } @@ -208,7 +223,7 @@ export async function setupListPagination( pageIndex = newPageIndex; const cachedPage = pages[newPageIndex]; - if (isInteractive()) { + if (enableInteractive) { console.clear(); } @@ -257,7 +272,7 @@ export async function setupListPagination( pageIndex--; const prevPage = pages[pageIndex]; - if (isInteractive()) { + if (enableInteractive) { console.clear(); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c01f41c39..59feaaa2e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -421,6 +421,9 @@ importers: '@oclif/plugin-help': specifier: 6.2.31 version: 6.2.31(typescript@5.9.3) + '@oclif/plugin-warn-if-update-available': + specifier: 3.1.53 + version: 3.1.53(typescript@5.9.3) '@swc/core': specifier: 'catalog:' version: 1.15.3 @@ -3473,6 +3476,10 @@ packages: resolution: {integrity: sha512-o4xR98DEFf+VqY+M9B3ZooTm2T/mlGvyBHwHcnsPJCEnvzHqEA9xUlCUK4jm7FBXHhkppziMgCC2snsueLoIpQ==} engines: {node: '>=18.0.0'} + '@oclif/plugin-warn-if-update-available@3.1.53': + resolution: {integrity: sha512-ALxKMNFFJQJV1Z2OMVTV+q7EbKHhnTAPcTgkgHeXCNdW5nFExoXuwusZLS4Zv2o83j9UoDx1R/CSX7QZVgEHTA==} + engines: {node: '>=18.0.0'} + '@octokit/app@16.1.2': resolution: {integrity: sha512-8j7sEpUYVj18dxvh0KWj6W/l6uAiVRBl1JBDVRqH1VHKAO/G5eRVl4yEoYACjakWers1DjUkcCHyJNQK47JqyQ==} engines: {node: '>= 20'} @@ -4503,6 +4510,18 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@pnpm/config.env-replace@1.1.0': + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + + '@pnpm/network.ca-file@1.0.2': + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + + '@pnpm/npm-conf@2.3.1': + resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} + engines: {node: '>=12'} + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -7559,6 +7578,9 @@ packages: confbox@0.2.2: resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + consola@3.4.2: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} @@ -9010,6 +9032,9 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -9136,6 +9161,10 @@ packages: http-cache-semantics@4.2.0: resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + http-call@5.3.0: + resolution: {integrity: sha512-ahwimsC23ICE4kPl9xTBjKB4inbRaeLyZeRunC/1Jy/Z6X8tv22MEAjK+KBOMSVLaqXPTTmd8638waVIKLGx2w==} + engines: {node: '>=8.0.0'} + http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -9376,6 +9405,10 @@ packages: is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + is-retry-allowed@1.2.0: + resolution: {integrity: sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==} + engines: {node: '>=0.10.0'} + is-ssh@1.4.1: resolution: {integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==} @@ -9520,6 +9553,9 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + json-parse-better-errors@1.0.2: + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} + json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} @@ -10812,6 +10848,10 @@ packages: resolution: {integrity: sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==} engines: {node: '>=14'} + parse-json@4.0.0: + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -11273,6 +11313,9 @@ packages: property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + protobufjs@7.5.4: resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} engines: {node: '>=12.0.0'} @@ -11545,6 +11588,10 @@ packages: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true + registry-auth-token@5.1.0: + resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} + engines: {node: '>=14'} + rehype-harden@1.1.5: resolution: {integrity: sha512-JrtBj5BVd/5vf3H3/blyJatXJbzQfRT9pJBmjafbTaPouQCAKxHwRyCc7dle9BXQKxv4z1OzZylz/tNamoiG3A==} @@ -15727,6 +15774,18 @@ snapshots: transitivePeerDependencies: - typescript + '@oclif/plugin-warn-if-update-available@3.1.53(typescript@5.9.3)': + dependencies: + '@oclif/core': 4.0.0(typescript@5.9.3) + ansis: 3.17.0 + debug: 4.4.3(supports-color@8.1.1) + http-call: 5.3.0 + lodash: 4.17.21 + registry-auth-token: 5.1.0 + transitivePeerDependencies: + - supports-color + - typescript + '@octokit/app@16.1.2': dependencies: '@octokit/auth-app': 8.1.2 @@ -16412,6 +16471,18 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@pnpm/config.env-replace@1.1.0': {} + + '@pnpm/network.ca-file@1.0.2': + dependencies: + graceful-fs: 4.2.10 + + '@pnpm/npm-conf@2.3.1': + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + '@polka/url@1.0.0-next.29': {} '@poppinss/colors@4.1.5': @@ -20548,6 +20619,11 @@ snapshots: confbox@0.2.2: {} + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + consola@3.4.2: {} content-disposition@1.0.1: {} @@ -22144,6 +22220,8 @@ snapshots: gopd@1.2.0: {} + graceful-fs@4.2.10: {} + graceful-fs@4.2.11: {} gray-matter@4.0.3: @@ -22363,6 +22441,17 @@ snapshots: http-cache-semantics@4.2.0: {} + http-call@5.3.0: + dependencies: + content-type: 1.0.5 + debug: 4.4.3(supports-color@8.1.1) + is-retry-allowed: 1.2.0 + is-stream: 2.0.1 + parse-json: 4.0.0 + tunnel-agent: 0.6.0 + transitivePeerDependencies: + - supports-color + http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -22448,8 +22537,7 @@ snapshots: inherits@2.0.4: {} - ini@1.3.8: - optional: true + ini@1.3.8: {} ini@4.1.1: {} @@ -22560,6 +22648,8 @@ snapshots: dependencies: '@types/estree': 1.0.8 + is-retry-allowed@1.2.0: {} + is-ssh@1.4.1: dependencies: protocols: 2.0.2 @@ -22673,6 +22763,8 @@ snapshots: json-buffer@3.0.1: optional: true + json-parse-better-errors@1.0.2: {} + json-parse-even-better-errors@2.3.1: {} json-schema-ref-resolver@3.0.0: @@ -24876,6 +24968,11 @@ snapshots: parse-gitignore@2.0.0: {} + parse-json@4.0.0: + dependencies: + error-ex: 1.3.4 + json-parse-better-errors: 1.0.2 + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.27.1 @@ -25334,6 +25431,8 @@ snapshots: property-information@7.1.0: {} + proto-list@1.2.4: {} + protobufjs@7.5.4: dependencies: '@protobufjs/aspromise': 1.1.2 @@ -25775,6 +25874,10 @@ snapshots: regexp-tree@0.1.27: {} + registry-auth-token@5.1.0: + dependencies: + '@pnpm/npm-conf': 2.3.1 + rehype-harden@1.1.5: {} rehype-katex@7.0.1: @@ -26787,7 +26890,6 @@ snapshots: tunnel-agent@0.6.0: dependencies: safe-buffer: 5.2.1 - optional: true turbo-darwin-64@2.5.4: optional: true