Skip to content

Commit f87c45e

Browse files
committed
fix(deps): replace ora and log-symbols with tiny dep
This should reduce our package size. I also added some missing types along the way.
1 parent 8a51e34 commit f87c45e

File tree

13 files changed

+2939
-3216
lines changed

13 files changed

+2939
-3216
lines changed

package-lock.json

+2,860-3,124
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,13 @@
138138
"lambda-local": "2.2.0",
139139
"locate-path": "7.2.0",
140140
"lodash": "4.17.21",
141-
"log-symbols": "6.0.0",
142141
"log-update": "6.1.0",
143142
"maxstache": "1.0.7",
144143
"maxstache-stream": "1.0.4",
145144
"multiparty": "4.2.3",
146145
"netlify": "13.3.3",
147146
"netlify-redirector": "0.5.0",
148147
"node-fetch": "3.3.2",
149-
"ora": "8.1.1",
150148
"p-filter": "4.1.0",
151149
"p-map": "7.0.3",
152150
"p-wait-for": "5.0.2",
@@ -175,6 +173,7 @@
175173
"wait-port": "1.1.0",
176174
"write-file-atomic": "5.0.1",
177175
"ws": "8.18.0",
176+
"yocto-spinner": "0.2.0",
178177
"zod": "3.23.8"
179178
},
180179
"devDependencies": {

scripts/prepare-for-publish.js

+7-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { dirname, join } from 'path'
33
import { fileURLToPath } from 'url'
44

55
import execa from 'execa'
6-
import ora from 'ora'
6+
import yoctoSpinner from 'yocto-spinner'
77

88
// These scripts from package.json need to be preserved on publish
99
const preserveScripts = new Set([
@@ -15,8 +15,7 @@ const preserveScripts = new Set([
1515
'prepublishOnly',
1616
])
1717

18-
let spinner = ora({
19-
spinner: 'star',
18+
let spinner = yoctoSpinner({
2019
text: 'Patching package.json (removing devDependencies, scripts, etc)',
2120
}).start()
2221

@@ -39,18 +38,16 @@ pkgJson.scripts.postinstall = pkgJson.scripts['postinstall-pack']
3938
delete pkgJson.scripts['postinstall-pack']
4039

4140
await writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2))
42-
spinner.succeed()
41+
spinner.success()
4342

44-
spinner = ora({
45-
spinner: 'star',
43+
spinner = yoctoSpinner({
4644
text: 'Running `npm install --no-audit`',
4745
}).start()
4846
await execa('npm', ['install', '--no-audit'])
49-
spinner.succeed()
47+
spinner.success()
5048

51-
spinner = ora({
52-
spinner: 'star',
49+
spinner = yoctoSpinner({
5350
text: 'Running `npm shrinkwrap`',
5451
}).start()
5552
await execa('npm', ['shrinkwrap'])
56-
spinner.succeed()
53+
spinner.success()

src/commands/deploy/deploy.ts

+10-20
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { getBootstrapURL } from '../../lib/edge-functions/bootstrap.js'
1717
import { featureFlags as edgeFunctionsFeatureFlags } from '../../lib/edge-functions/consts.js'
1818
import { normalizeFunctionsConfig } from '../../lib/functions/config.js'
1919
import { BACKGROUND_FUNCTIONS_WARNING } from '../../lib/log.js'
20-
import { startSpinner, stopSpinner } from '../../lib/spinner.js'
20+
import { type Spinner, startSpinner, stopSpinner } from '../../lib/spinner.js'
2121
import { detectFrameworkSettings, getDefaultConfig } from '../../utils/build-info.js'
2222
import {
2323
NETLIFYDEV,
@@ -33,7 +33,7 @@ import {
3333
APIError,
3434
} from '../../utils/command-helpers.js'
3535
import { DEFAULT_DEPLOY_TIMEOUT } from '../../utils/deploy/constants.js'
36-
import { deploySite } from '../../utils/deploy/deploy-site.js'
36+
import { type DeployEvent, deploySite } from '../../utils/deploy/deploy-site.js'
3737
import { getEnvelopeEnv } from '../../utils/env/index.js'
3838
import { getFunctionsManifestPath, getInternalFunctionsDir } from '../../utils/functions/index.js'
3939
import openBrowser from '../../utils/open-browser.js'
@@ -309,40 +309,30 @@ const reportDeployError = ({ error_, failAndExit }) => {
309309
}
310310

311311
const deployProgressCb = function () {
312-
/**
313-
* @type {Record<string, import('ora').Ora>}
314-
*/
315-
const events = {}
316-
// @ts-expect-error TS(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
317-
return (event) => {
312+
const spinnersByType: Record<DeployEvent['type'], Spinner> = {}
313+
return (event: DeployEvent) => {
318314
switch (event.phase) {
319315
case 'start': {
320-
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
321-
events[event.type] = startSpinner({
316+
spinnersByType[event.type] = startSpinner({
322317
text: event.msg,
323318
})
324319
return
325320
}
326321
case 'progress': {
327-
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
328-
const spinner = events[event.type]
322+
const spinner = spinnersByType[event.type]
329323
if (spinner) {
330324
spinner.text = event.msg
331325
}
332326
return
333327
}
334328
case 'error':
335-
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
336-
stopSpinner({ error: true, spinner: events[event.type], text: event.msg })
337-
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
338-
delete events[event.type]
329+
stopSpinner({ error: true, spinner: spinnersByType[event.type], text: event.msg })
330+
delete spinnersByType[event.type]
339331
return
340332
case 'stop':
341333
default: {
342-
// @ts-expect-error TS(2345) FIXME: Argument of type '{ spinner: any; text: any; }' is... Remove this comment to see the full error message
343-
stopSpinner({ spinner: events[event.type], text: event.msg })
344-
// @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
345-
delete events[event.type]
334+
stopSpinner({ spinner: spinnersByType[event.type], text: event.msg })
335+
delete spinnersByType[event.type]
346336
}
347337
}
348338
}

src/commands/functions/functions-create.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { findUp } from 'find-up'
1111
import fuzzy from 'fuzzy'
1212
import inquirer from 'inquirer'
1313
import fetch from 'node-fetch'
14-
import ora from 'ora'
14+
import yoctoSpinner from 'yocto-spinner'
1515

1616
import { fileExistsAsync } from '../../lib/fs.js'
1717
import { getAddons, getCurrentAddon, getSiteData } from '../../utils/addons/prepare.js'
@@ -45,6 +45,11 @@ const languages = [
4545
{ name: 'Rust', value: 'rust' },
4646
]
4747

48+
const MOON_SPINNER = {
49+
interval: 80,
50+
frames: ['🌑 ', '🌒 ', '🌓 ', '🌔 ', '🌕 ', '🌖 ', '🌗 ', '🌘 '],
51+
}
52+
4853
/**
4954
* prompt for a name if name not supplied
5055
* @param {string} argumentName
@@ -544,12 +549,12 @@ const scaffoldFromTemplate = async function (command, options, argumentName, fun
544549

545550
// npm install
546551
if (functionPackageJson !== undefined) {
547-
const spinner = ora({
552+
const spinner = yoctoSpinner({
548553
text: `Installing dependencies for ${name}`,
549-
spinner: 'moon',
554+
spinner: MOON_SPINNER,
550555
}).start()
551556
await installDeps({ functionPackageJson, functionPath, functionsDir })
552-
spinner.succeed(`Installed dependencies for ${name}`)
557+
spinner.success(`Installed dependencies for ${name}`)
553558
}
554559

555560
if (funcType === 'edge') {

src/commands/sites/sites-list.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@ import BaseCommand from '../base-command.js'
88

99
export const sitesList = async (options: OptionValues, command: BaseCommand) => {
1010
const { api } = command.netlify
11-
/** @type {import('ora').Ora} */
1211
let spinner
1312
if (!options.json) {
1413
spinner = startSpinner({ text: 'Loading your sites' })
1514
}
1615
await command.authenticate()
1716

1817
const sites = await listSites({ api, options: { filter: 'all' } })
19-
if (!options.json) {
20-
// @ts-expect-error TS(2345) FIXME: Argument of type '{ spinner: Ora | undefined; }' i... Remove this comment to see the full error message
18+
if (spinner) {
2119
stopSpinner({ spinner })
2220
}
2321

src/commands/watch/watch.ts

+5-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { OptionValues } from 'commander'
22
import pWaitFor from 'p-wait-for'
33
import prettyjson from 'prettyjson'
4+
import type { NetlifyAPI } from 'netlify'
45

5-
import { startSpinner, stopSpinner } from '../../lib/spinner.js'
6+
import { type Spinner, startSpinner, stopSpinner } from '../../lib/spinner.js'
67
import { chalk, error, log } from '../../utils/command-helpers.js'
78
import BaseCommand from '../base-command.js'
89
import { init } from '../init/init.js'
@@ -15,28 +16,18 @@ const BUILD_FINISH_INTERVAL = 1e3
1516
// 20 minutes
1617
const BUILD_FINISH_TIMEOUT = 12e5
1718

18-
/**
19-
*
20-
* @param {import('netlify').NetlifyAPI} api
21-
* @param {string} siteId
22-
* @param {import('ora').Ora} spinner
23-
* @returns {Promise<boolean>}
24-
*/
25-
// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type.
26-
const waitForBuildFinish = async function (api, siteId, spinner) {
19+
const waitForBuildFinish = async function (api: NetlifyAPI, siteId: string, spinner: Spinner) {
2720
let firstPass = true
2821

2922
const waitForBuildToFinish = async function () {
3023
const builds = await api.listSiteBuilds({ siteId })
3124
// build.error
32-
// @ts-expect-error TS(7006) FIXME: Parameter 'build' implicitly has an 'any' type.
3325
const currentBuilds = builds.filter((build) => !build.done)
3426

3527
// if build.error
3628
// @TODO implement build error messages into this
3729

3830
if (!currentBuilds || currentBuilds.length === 0) {
39-
// @ts-expect-error TS(2345) FIXME: Argument of type '{ spinner: any; }' is not assign... Remove this comment to see the full error message
4031
stopSpinner({ spinner })
4132
return true
4233
}
@@ -64,7 +55,7 @@ export const watch = async (options: OptionValues, command: BaseCommand) => {
6455
if (!siteId) {
6556
// TODO: build init command
6657
const siteData = await init({}, command)
67-
siteId = siteData.id
58+
siteId = siteData.id as string
6859
}
6960

7061
// wait for 1 sec for everything to kickoff
@@ -101,7 +92,7 @@ export const watch = async (options: OptionValues, command: BaseCommand) => {
10192

10293
const noActiveBuilds = await waitForBuildFinish(client, siteId, spinner)
10394

104-
const siteData = await client.getSite({ siteId: siteId as string })
95+
const siteData = await client.getSite({ siteId })
10596

10697
const message = chalk.cyanBright.bold.underline(noActiveBuilds ? 'Last build' : 'Deploy complete')
10798
log()

src/lib/api.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const MAX_PAGES = 10
1616
const MAX_PER_PAGE = 100
1717

1818
// @ts-expect-error TS(7023) FIXME: 'listSites' implicitly has return type 'any' becau... Remove this comment to see the full error message
19-
export const listSites = async ({ api, options }): SiteInfo[] => {
19+
export const listSites = async ({ api, options }): Promise<SiteInfo[]> => {
2020
const { maxPages = MAX_PAGES, page = FIRST_PAGE, ...rest } = options
2121
const sites = await api.listSites({ page, per_page: MAX_PER_PAGE, ...rest })
2222
// TODO: use pagination headers when js-client returns them

src/lib/edge-functions/proxy.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { FeatureFlags, getFeatureFlagsFromSiteInfo } from '../../utils/feature-f
1313
import { BlobsContextWithEdgeAccess } from '../blobs/blobs.js'
1414
import { getGeoLocation } from '../geo-location.js'
1515
import { getPathInProject } from '../settings.js'
16-
import { startSpinner, stopSpinner } from '../spinner.js'
16+
import { type Spinner, startSpinner, stopSpinner } from '../spinner.js'
1717

1818
import { getBootstrapURL } from './bootstrap.js'
1919
import { DIST_IMPORT_MAP_PATH, EDGE_FUNCTIONS_SERVE_FOLDER } from './consts.js'
@@ -25,7 +25,7 @@ const headersSymbol = Symbol('Edge Functions Headers')
2525
const LOCAL_HOST = '127.0.0.1'
2626

2727
const getDownloadUpdateFunctions = () => {
28-
let spinner: ReturnType<typeof startSpinner>
28+
let spinner: Spinner
2929

3030
const onAfterDownload = (error_: unknown) => {
3131
stopSpinner({ error: Boolean(error_), spinner })

src/lib/spinner.ts

+18-14
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,38 @@
1-
import logSymbols from 'log-symbols'
2-
import ora, { Ora } from 'ora'
1+
import yoctoSpinner, { Spinner } from 'yocto-spinner'
2+
3+
const DOTS_SPINNER = {
4+
interval: 80,
5+
frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],
6+
}
37

48
/**
59
* Creates a spinner with the following text
610
*/
711
export const startSpinner = ({ text }: { text: string }) =>
8-
ora({
12+
yoctoSpinner({
913
text,
14+
spinner: DOTS_SPINNER,
1015
}).start()
1116

1217
/**
1318
* Stops the spinner with the following text
1419
*/
15-
export const stopSpinner = ({ error, spinner, text }: { error: boolean; spinner: Ora; text?: string }) => {
20+
export const stopSpinner = ({ error, spinner, text }: { error?: boolean; spinner: Spinner; text?: string }) => {
1621
if (!spinner) {
1722
return
1823
}
19-
// TODO: refactor no package needed `log-symbols` for that
20-
const symbol = error ? logSymbols.error : logSymbols.success
21-
spinner.stopAndPersist({
22-
text,
23-
symbol,
24-
})
24+
if (error === true) {
25+
spinner.error(text)
26+
} else {
27+
spinner.stop(text)
28+
}
2529
}
2630

2731
/**
2832
* Clears the spinner
2933
*/
30-
export const clearSpinner = ({ spinner }: { spinner: Ora }) => {
31-
if (spinner) {
32-
spinner.stop()
33-
}
34+
export const clearSpinner = ({ spinner }: { spinner: Spinner }) => {
35+
spinner.clear()
3436
}
37+
38+
export type { Spinner }

src/utils/deploy/deploy-site.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ const buildStatsString = (possibleParts: Array<string | false | undefined>) => {
2828
return parts.length > 1 ? `${message} and ${parts[parts.length - 1]}` : message
2929
}
3030

31+
// TODO(serhalp) This is alternatingly called "event", "status", and "progress". Standardize.
32+
export interface DeployEvent {
33+
type: string
34+
msg: string
35+
phase: 'start' | 'progress' | 'error' | 'stop'
36+
}
37+
3138
export const deploySite = async (
3239
command: BaseCommand,
3340
api: $TSFixMe,
@@ -74,7 +81,7 @@ export const deploySite = async (
7481
deployTimeout?: number
7582
draft?: boolean
7683
maxRetry?: number
77-
statusCb?: (status: { type: string; msg: string; phase: string }) => void
84+
statusCb?: (status: DeployEvent) => void
7885
syncFileLimit?: number
7986
tmpDir?: string
8087
fnDir?: string[]

src/utils/framework-server.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ export const startFrameworkServer = async function ({
4444
await rm(settings.dist, { recursive: true, force: true })
4545
}
4646

47-
runCommand(settings.command, { env: settings.env, spinner, cwd })
47+
if (settings.command) {
48+
runCommand(settings.command, { env: settings.env, spinner, cwd })
49+
}
4850

4951
let port: { open: boolean; ipVersion?: 4 | 6 } | undefined
5052
try {

0 commit comments

Comments
 (0)