diff --git a/.changeset/rotten-apples-happen.md b/.changeset/rotten-apples-happen.md new file mode 100644 index 000000000000..d8f30231ce64 --- /dev/null +++ b/.changeset/rotten-apples-happen.md @@ -0,0 +1,5 @@ +--- +"wrangler": patch +--- + +Internal refactor to remove React/ink from all non-`wrangler dev` flows diff --git a/packages/wrangler/src/__tests__/d1/create.test.ts b/packages/wrangler/src/__tests__/d1/create.test.ts index f72125e2c490..f287342e5999 100644 --- a/packages/wrangler/src/__tests__/d1/create.test.ts +++ b/packages/wrangler/src/__tests__/d1/create.test.ts @@ -65,9 +65,10 @@ describe("create", () => { Created your new D1 database. [[d1_databases]] - binding = \\"DB\\" # i.e. available in your Worker on env.DB + binding = \\"DB\\" database_name = \\"test\\" - database_id = \\"51e7c314-456e-4167-b6c3-869ad188fc23\\"" + database_id = \\"51e7c314-456e-4167-b6c3-869ad188fc23\\" + " `); }); }); diff --git a/packages/wrangler/src/ai/createFinetune.tsx b/packages/wrangler/src/ai/createFinetune.ts similarity index 100% rename from packages/wrangler/src/ai/createFinetune.tsx rename to packages/wrangler/src/ai/createFinetune.ts diff --git a/packages/wrangler/src/ai/listCatalog.tsx b/packages/wrangler/src/ai/listCatalog.ts similarity index 100% rename from packages/wrangler/src/ai/listCatalog.tsx rename to packages/wrangler/src/ai/listCatalog.ts diff --git a/packages/wrangler/src/ai/listFinetune.tsx b/packages/wrangler/src/ai/listFinetune.ts similarity index 100% rename from packages/wrangler/src/ai/listFinetune.tsx rename to packages/wrangler/src/ai/listFinetune.ts diff --git a/packages/wrangler/src/api/pages/deploy.tsx b/packages/wrangler/src/api/pages/deploy.ts similarity index 100% rename from packages/wrangler/src/api/pages/deploy.tsx rename to packages/wrangler/src/api/pages/deploy.ts diff --git a/packages/wrangler/src/d1/backups.tsx b/packages/wrangler/src/d1/backups.ts similarity index 93% rename from packages/wrangler/src/d1/backups.tsx rename to packages/wrangler/src/d1/backups.ts index e56ab0e9db0e..9dd921773ab1 100644 --- a/packages/wrangler/src/d1/backups.tsx +++ b/packages/wrangler/src/d1/backups.ts @@ -1,12 +1,10 @@ import fs from "node:fs/promises"; import * as path from "path"; -import Table from "ink-table"; import { fetchResult } from "../cfetch"; import { performApiFetch } from "../cfetch/internal"; import { withConfig } from "../config"; import { logger } from "../logger"; import { requireAuth } from "../user"; -import { renderToString } from "../utils/render"; import { formatBytes, formatTimeAgo } from "./formatTimeAgo"; import { Name } from "./options"; import { getDatabaseByNameOrBinding } from "./utils"; @@ -32,13 +30,13 @@ export const ListHandler = withConfig( ); const backups: Backup[] = await listBackups(accountId, db.uuid); - logger.log( - renderToString( -
- ) + logger.table( + backups.map((b) => ({ + created_at: b.created_at, + id: b.id, + num_tables: String(b.num_tables), + size: b.size ?? "", + })) ); } ); @@ -95,13 +93,13 @@ export const CreateHandler = withConfig( ); const backup: Backup = await createBackup(accountId, db.uuid); - logger.log( - renderToString( -
- ) + logger.table( + [backup].map((b) => ({ + created_at: b.created_at, + id: b.id, + num_tables: String(b.num_tables), + size: b.size ?? "", + })) ); } ); diff --git a/packages/wrangler/src/d1/create.tsx b/packages/wrangler/src/d1/create.ts similarity index 72% rename from packages/wrangler/src/d1/create.tsx rename to packages/wrangler/src/d1/create.ts index 7c0a647353e6..ade04536e395 100644 --- a/packages/wrangler/src/d1/create.tsx +++ b/packages/wrangler/src/d1/create.ts @@ -1,11 +1,10 @@ -import { Box, Text } from "ink"; +import TOML from "@iarna/toml"; import { printWranglerBanner } from ".."; import { fetchResult } from "../cfetch"; import { withConfig } from "../config"; import { UserError } from "../errors"; import { logger } from "../logger"; import { requireAuth } from "../user"; -import { renderToString } from "../utils/render"; import { LOCATION_CHOICES } from "./constants"; import type { CommonYargsArgv, @@ -63,26 +62,21 @@ export const Handler = withConfig( } logger.log( - renderToString( - - - ✅ Successfully created DB '{db.name}' - {db.created_in_region - ? ` in region ${db.created_in_region}` - : location - ? ` using primary location hint ${location}` - : ``} - - Created your new D1 database. -   - [[d1_databases]] - - binding = "DB" # i.e. available in your Worker on env.DB - - database_name = "{db.name}" - database_id = "{db.uuid}" - - ) + `✅ Successfully created DB '${db.name}'${ + db.created_in_region + ? ` in region ${db.created_in_region}` + : location + ? ` using primary location hint ${location}` + : `` + }` + ); + logger.log("Created your new D1 database.\n"); + logger.log( + TOML.stringify({ + d1_databases: [ + { binding: "DB", database_name: db.name, database_id: db.uuid }, + ], + }) ); } ); diff --git a/packages/wrangler/src/d1/execute.tsx b/packages/wrangler/src/d1/execute.ts similarity index 95% rename from packages/wrangler/src/d1/execute.tsx rename to packages/wrangler/src/d1/execute.ts index 645708f8521a..a3a71ee3c209 100644 --- a/packages/wrangler/src/d1/execute.tsx +++ b/packages/wrangler/src/d1/execute.ts @@ -3,12 +3,10 @@ import assert from "node:assert"; import path from "node:path"; import { spinnerWhile } from "@cloudflare/cli/interactive"; import chalk from "chalk"; -import { Static, Text } from "ink"; -import Table from "ink-table"; import md5File from "md5-file"; import { Miniflare } from "miniflare"; import { fetch } from "undici"; -import { printWranglerBanner } from "../"; +import { printWranglerBanner } from ".."; import { fetchResult } from "../cfetch"; import { readConfig } from "../config"; import { getLocalPersistencePath } from "../dev/get-local-persistence-path"; @@ -18,7 +16,6 @@ import { logger } from "../logger"; import { APIError, readFileSync } from "../parse"; import { readableRelative } from "../paths"; import { requireAuth } from "../user"; -import { renderToString } from "../utils/render"; import * as options from "./options"; import splitSqlQuery from "./splitter"; import { getDatabaseByNameOrBinding, getDatabaseInfoFromConfig } from "./utils"; @@ -144,29 +141,25 @@ export const Handler = async (args: HandlerOptions): Promise => { } if (isInteractive && !json) { - // Render table if single result - logger.log( - renderToString( - - {(result) => { - // batch results - if (!Array.isArray(result)) { - const { results, query } = result; - - if (Array.isArray(results) && results.length > 0) { - const shortQuery = shorten(query, 48); - return ( - <> - {shortQuery ? {shortQuery} : null} -
- - ); - } - } - }} -
- ) - ); + for (const result of response) { + if (!Array.isArray(result)) { + const { results, query } = result; + + if (Array.isArray(results) && results.length > 0) { + const shortQuery = shorten(query, 48); + if (shortQuery) { + logger.log(chalk.dim(shortQuery)); + } + logger.table( + results.map((r) => + Object.fromEntries( + Object.entries(r).map(([k, v]) => [k, String(v)]) + ) + ) + ); + } + } + } } else { // set loggerLevel back to what it was before to actually output the JSON in stdout logger.loggerLevel = existingLogLevel; diff --git a/packages/wrangler/src/d1/info.tsx b/packages/wrangler/src/d1/info.ts similarity index 96% rename from packages/wrangler/src/d1/info.tsx rename to packages/wrangler/src/d1/info.ts index 1d6f2e8b134d..dfa460bd45b5 100644 --- a/packages/wrangler/src/d1/info.tsx +++ b/packages/wrangler/src/d1/info.ts @@ -1,11 +1,9 @@ -import Table from "ink-table"; import prettyBytes from "pretty-bytes"; import { printWranglerBanner } from ".."; import { fetchGraphqlResult } from "../cfetch"; import { withConfig } from "../config"; import { logger } from "../logger"; import { requireAuth } from "../user"; -import { renderToString } from "../utils/render"; import { getDatabaseByNameOrBinding, getDatabaseInfoFromId } from "./utils"; import type { CommonYargsArgv, @@ -132,7 +130,7 @@ export const Handler = withConfig( ) { value = v.toLocaleString(); } else { - value = v; + value = String(v); } return { [db.binding || ""]: k, @@ -141,7 +139,7 @@ export const Handler = withConfig( }); await printWranglerBanner(); - logger.log(renderToString()); + logger.table(data); } } ); diff --git a/packages/wrangler/src/d1/list.tsx b/packages/wrangler/src/d1/list.ts similarity index 90% rename from packages/wrangler/src/d1/list.tsx rename to packages/wrangler/src/d1/list.ts index 5073a7f90274..4ede458d3a70 100644 --- a/packages/wrangler/src/d1/list.tsx +++ b/packages/wrangler/src/d1/list.ts @@ -1,10 +1,8 @@ -import Table from "ink-table"; import { printWranglerBanner } from ".."; import { fetchResult } from "../cfetch"; import { withConfig } from "../config"; import { logger } from "../logger"; import { requireAuth } from "../user"; -import { renderToString } from "../utils/render"; import type { CommonYargsArgv, StrictYargsOptionsToInterface, @@ -29,7 +27,13 @@ export const Handler = withConfig( logger.log(JSON.stringify(dbs, null, 2)); } else { await printWranglerBanner(); - logger.log(renderToString(
)); + logger.table( + dbs.map((db) => + Object.fromEntries( + Object.entries(db).map(([k, v]) => [k, String(v ?? "")]) + ) + ) + ); } } ); diff --git a/packages/wrangler/src/d1/migrations/apply.tsx b/packages/wrangler/src/d1/migrations/apply.ts similarity index 84% rename from packages/wrangler/src/d1/migrations/apply.tsx rename to packages/wrangler/src/d1/migrations/apply.ts index 8aff6c99a648..eb4954d744a5 100644 --- a/packages/wrangler/src/d1/migrations/apply.tsx +++ b/packages/wrangler/src/d1/migrations/apply.ts @@ -1,8 +1,6 @@ import assert from "node:assert"; import fs from "node:fs"; import path from "path"; -import { Box, Text } from "ink"; -import Table from "ink-table"; import { printWranglerBanner } from "../.."; import { withConfig } from "../../config"; import { confirm } from "../../dialogs"; @@ -11,7 +9,6 @@ import { CI } from "../../is-ci"; import isInteractive from "../../is-interactive"; import { logger } from "../../logger"; import { requireAuth } from "../../user"; -import { renderToString } from "../../utils/render"; import { createBackup } from "../backups"; import { DEFAULT_MIGRATION_PATH, DEFAULT_MIGRATION_TABLE } from "../constants"; import { executeSql } from "../execute"; @@ -112,17 +109,12 @@ export const ApplyHandler = withConfig( }); if (unappliedMigrations.length === 0) { - logger.log(renderToString(✅ No migrations to apply!)); + logger.log("✅ No migrations to apply!"); return; } - logger.log( - renderToString( - - Migrations to be applied: -
-
- ) - ); + logger.log("Migrations to be applied:"); + logger.table(unappliedMigrations.map((m) => ({ name: m.name }))); + const ok = await confirm( `About to apply ${unappliedMigrations.length} migration(s) Your database may not be available to serve requests during the migration, continue?` @@ -140,7 +132,7 @@ Your database may not be available to serve requests during the migration, conti const accountId = await requireAuth(config); const dbInfo = await getDatabaseInfoFromId(accountId, databaseInfo?.uuid); if (dbInfo.version === "alpha") { - logger.log(renderToString(🕒 Creating backup...)); + logger.log("🕒 Creating backup..."); await createBackup(accountId, databaseInfo.uuid); } } @@ -202,24 +194,14 @@ Your database may not be available to serve requests during the migration, conti migration.status = success ? "✅" : "❌"; - logger.log( - renderToString( - - - {errorNotes.length > 0 && ( - -   - - ❌ Migration {migration.name}{" "} - {errorNotes.length > 0 - ? "failed with the following errors:" - : ""} - - - )} - - ) + logger.table( + unappliedMigrations.map((m) => ({ name: m.name, status: m.status })) ); + if (errorNotes.length > 0) { + logger.error( + `Migration ${migration.name} failed with the following errors:` + ); + } if (errorNotes.length > 0) { throw new UserError( diff --git a/packages/wrangler/src/d1/migrations/create.tsx b/packages/wrangler/src/d1/migrations/create.ts similarity index 82% rename from packages/wrangler/src/d1/migrations/create.tsx rename to packages/wrangler/src/d1/migrations/create.ts index 40ef801303ee..780a5a797dee 100644 --- a/packages/wrangler/src/d1/migrations/create.tsx +++ b/packages/wrangler/src/d1/migrations/create.ts @@ -1,11 +1,9 @@ import fs from "node:fs"; import path from "path"; -import { Box, Text } from "ink"; import { printWranglerBanner } from "../.."; import { withConfig } from "../../config"; import { UserError } from "../../errors"; import { logger } from "../../logger"; -import { renderToString } from "../../utils/render"; import { DEFAULT_MIGRATION_PATH } from "../constants"; import { Database } from "../options"; import { getDatabaseInfoFromConfig } from "../utils"; @@ -55,20 +53,9 @@ export const CreateHandler = withConfig( `-- Migration number: ${nextMigrationNumber} \t ${new Date().toISOString()}\n` ); - logger.log( - renderToString( - - - ✅ Successfully created Migration '{newMigrationName}'! - -   - The migration is available for editing here - - {migrationsPath}/{newMigrationName} - - - ) - ); + logger.log(`✅ Successfully created Migration '${newMigrationName}'!\n`); + logger.log(`The migration is available for editing here`); + logger.log(`${migrationsPath}/{newMigrationName}`); } ); diff --git a/packages/wrangler/src/d1/migrations/list.tsx b/packages/wrangler/src/d1/migrations/list.ts similarity index 84% rename from packages/wrangler/src/d1/migrations/list.tsx rename to packages/wrangler/src/d1/migrations/list.ts index 3b0111991b6a..e70f000880cc 100644 --- a/packages/wrangler/src/d1/migrations/list.tsx +++ b/packages/wrangler/src/d1/migrations/list.ts @@ -1,12 +1,9 @@ import path from "path"; -import { Box, Text } from "ink"; -import Table from "ink-table"; import { printWranglerBanner } from "../.."; import { withConfig } from "../../config"; import { UserError } from "../../errors"; import { logger } from "../../logger"; import { requireAuth } from "../../user"; -import { renderToString } from "../../utils/render"; import { DEFAULT_MIGRATION_PATH, DEFAULT_MIGRATION_TABLE } from "../constants"; import { getDatabaseInfoFromConfig } from "../utils"; import { @@ -89,17 +86,10 @@ export const ListHandler = withConfig( }); if (unappliedMigrations.length === 0) { - logger.log(renderToString(✅ No migrations to apply!)); + logger.log("✅ No migrations to apply!"); return; } - - logger.log( - renderToString( - - Migrations to be applied: -
-
- ) - ); + logger.log("Migrations to be applied:"); + logger.table(unappliedMigrations.map((m) => ({ Name: m.Name }))); } ); diff --git a/packages/wrangler/src/pages/deploy.tsx b/packages/wrangler/src/pages/deploy.ts similarity index 97% rename from packages/wrangler/src/pages/deploy.tsx rename to packages/wrangler/src/pages/deploy.ts index 5b1fb6332aa8..e8a3e85298fc 100644 --- a/packages/wrangler/src/pages/deploy.tsx +++ b/packages/wrangler/src/pages/deploy.ts @@ -1,11 +1,9 @@ import { execSync } from "node:child_process"; -import { render, Text } from "ink"; -import SelectInput from "ink-select-input"; import { deploy } from "../api/pages/deploy"; import { fetchResult } from "../cfetch"; import { findWranglerToml, readConfig } from "../config"; import { getConfigCache, saveToConfigCache } from "../config-cache"; -import { prompt } from "../dialogs"; +import { prompt, select } from "../dialogs"; import { FatalError } from "../errors"; import { logger } from "../logger"; import * as metrics from "../metrics"; @@ -471,18 +469,7 @@ function promptSelectExistingOrNewProject( message: string, items: NewOrExistingItem[] ): Promise<"new" | "existing"> { - return new Promise<"new" | "existing">((resolve) => { - const { unmount } = render( - <> - {message} - { - resolve(selected.value as "new" | "existing"); - unmount(); - }} - /> - - ); + return select(message, { + choices: items.map((i) => ({ title: i.label, value: i.value })), }); } diff --git a/packages/wrangler/src/pages/deployments.tsx b/packages/wrangler/src/pages/deployments.ts similarity index 94% rename from packages/wrangler/src/pages/deployments.tsx rename to packages/wrangler/src/pages/deployments.ts index 7047af5624d9..2de7612ab9f2 100644 --- a/packages/wrangler/src/pages/deployments.tsx +++ b/packages/wrangler/src/pages/deployments.ts @@ -1,4 +1,3 @@ -import Table from "ink-table"; import { format as timeagoFormat } from "timeago.js"; import { fetchResult } from "../cfetch"; import { getConfigCache, saveToConfigCache } from "../config-cache"; @@ -6,7 +5,6 @@ import { FatalError } from "../errors"; import { logger } from "../logger"; import * as metrics from "../metrics"; import { requireAuth } from "../user"; -import { renderToString } from "../utils/render"; import { PAGES_CONFIG_CACHE_FILENAME } from "./constants"; import { promptSelectProject } from "./prompt-select-project"; import type { @@ -79,6 +77,6 @@ export async function ListHandler({ projectName }: ListArgs) { account_id: accountId, }); - logger.log(renderToString(
)); + logger.table(data); await metrics.sendMetricsEvent("list pages deployments"); } diff --git a/packages/wrangler/src/pages/projects.tsx b/packages/wrangler/src/pages/projects.ts similarity index 97% rename from packages/wrangler/src/pages/projects.tsx rename to packages/wrangler/src/pages/projects.ts index 5297c85a2fa7..a76dd8cd1e79 100644 --- a/packages/wrangler/src/pages/projects.tsx +++ b/packages/wrangler/src/pages/projects.ts @@ -1,5 +1,4 @@ import { execSync } from "node:child_process"; -import Table from "ink-table"; import { format as timeagoFormat } from "timeago.js"; import { fetchResult } from "../cfetch"; import { getConfigCache, saveToConfigCache } from "../config-cache"; @@ -9,7 +8,6 @@ import { logger } from "../logger"; import * as metrics from "../metrics"; import { requireAuth } from "../user"; import { getCloudflareAccountIdFromEnv } from "../user/auth-variables"; -import { renderToString } from "../utils/render"; import { PAGES_CONFIG_CACHE_FILENAME } from "./constants"; import type { CommonYargsArgv, @@ -44,7 +42,7 @@ export async function ListHandler() { account_id: accountId, }); - logger.log(renderToString(
)); + logger.table(data); await metrics.sendMetricsEvent("list pages projects"); } diff --git a/packages/wrangler/src/pages/prompt-select-project.ts b/packages/wrangler/src/pages/prompt-select-project.ts new file mode 100644 index 000000000000..2ba395686d15 --- /dev/null +++ b/packages/wrangler/src/pages/prompt-select-project.ts @@ -0,0 +1,17 @@ +import { select } from "../dialogs"; +import { listProjects } from "./projects"; + +export async function promptSelectProject({ + accountId, +}: { + accountId: string; +}): Promise { + const projects = await listProjects({ accountId }); + + return select("Select a project:", { + choices: projects.map((project) => ({ + title: project.name, + value: project.name, + })), + }); +} diff --git a/packages/wrangler/src/pages/prompt-select-project.tsx b/packages/wrangler/src/pages/prompt-select-project.tsx deleted file mode 100644 index 46b2c7045b5b..000000000000 --- a/packages/wrangler/src/pages/prompt-select-project.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { render, Text } from "ink"; -import SelectInput from "ink-select-input"; -import { listProjects } from "./projects"; - -export async function promptSelectProject({ - accountId, -}: { - accountId: string; -}): Promise { - const projects = await listProjects({ accountId }); - - return new Promise((resolve) => { - const { unmount } = render( - <> - Select a project: - ({ - key: project.name, - label: project.name, - value: project, - }))} - onSelect={async (selected) => { - resolve(selected.value.name); - unmount(); - }} - /> - - ); - }); -} diff --git a/packages/wrangler/src/pages/upload.tsx b/packages/wrangler/src/pages/upload.ts similarity index 91% rename from packages/wrangler/src/pages/upload.tsx rename to packages/wrangler/src/pages/upload.ts index 484e99978d2b..139799ac741d 100644 --- a/packages/wrangler/src/pages/upload.tsx +++ b/packages/wrangler/src/pages/upload.ts @@ -1,7 +1,6 @@ import { mkdir, readFile, writeFile } from "node:fs/promises"; import { dirname } from "node:path"; -import { render, Text } from "ink"; -import Spinner from "ink-spinner"; +import { spinner } from "@cloudflare/cli/interactive"; import PQueue from "p-queue"; import { fetchResult } from "../cfetch"; import { FatalError } from "../errors"; @@ -189,7 +188,7 @@ export const upload = async ( } let counter = args.fileMap.size - sortedFiles.length; - const { rerender, unmount } = renderProgress(counter, args.fileMap.size); + const { update, stop } = renderProgress(counter, args.fileMap.size); const queue = new PQueue({ concurrency: BULK_UPLOAD_CONCURRENCY }); @@ -269,7 +268,7 @@ export const upload = async ( doUpload().then( () => { counter += bucket.files.length; - rerender(counter, args.fileMap.size); + update(counter, args.fileMap.size); }, (error) => { return Promise.reject( @@ -287,7 +286,7 @@ export const upload = async ( await queue.onIdle(); - unmount(); + stop(); const uploadMs = Date.now() - start; @@ -383,34 +382,18 @@ function formatTime(duration: number) { } function renderProgress(done: number, total: number) { + const s = spinner(); if (isInteractive()) { - const { rerender, unmount } = render( - - ); + s.start(`Uploading... (${done}/${total})\n`); return { - // eslint-disable-next-line @typescript-eslint/no-shadow - rerender(done: number, total: number) { - rerender(); - }, - unmount, + update: (d: number, t: number) => s.update(`Uploading... (${d}/${t})\n`), + stop: s.stop, }; } else { - // eslint-disable-next-line @typescript-eslint/no-shadow - const rerender = (done: number, total: number) => { - logger.log(`Uploading... (${done}/${total})`); + logger.log(`Uploading... (${done}/${total})`); + return { + update: (d: number, t: number) => logger.log(`Uploading... (${d}/${t})`), + stop: () => {}, }; - rerender(done, total); - return { rerender, unmount() {} }; } } - -function Progress({ done, total }: { done: number; total: number }) { - return ( - <> - - {isInteractive() ? : null} - {` Uploading... (${done}/${total})\n`} - - - ); -} diff --git a/packages/wrangler/src/pages/validate.tsx b/packages/wrangler/src/pages/validate.ts similarity index 100% rename from packages/wrangler/src/pages/validate.tsx rename to packages/wrangler/src/pages/validate.ts diff --git a/packages/wrangler/src/user/choose-account.tsx b/packages/wrangler/src/user/choose-account.ts similarity index 100% rename from packages/wrangler/src/user/choose-account.tsx rename to packages/wrangler/src/user/choose-account.ts diff --git a/packages/wrangler/src/vectorize/create.tsx b/packages/wrangler/src/vectorize/create.ts similarity index 100% rename from packages/wrangler/src/vectorize/create.tsx rename to packages/wrangler/src/vectorize/create.ts