Skip to content

refactor(many): convert ui-scripts to TypeScript and add tests#2578

Open
ToMESSKa wants to merge 1 commit into
masterfrom
INSTUI-5038-convert-ui-scripts-to-type-script
Open

refactor(many): convert ui-scripts to TypeScript and add tests#2578
ToMESSKa wants to merge 1 commit into
masterfrom
INSTUI-5038-convert-ui-scripts-to-type-script

Conversation

@ToMESSKa
Copy link
Copy Markdown
Contributor

@ToMESSKa ToMESSKa commented Jun 3, 2026

INSTUI-5038

ISSUE:

  • ui-scripts is not fully in TypeScrips and is missing some tests

TEST PLAN:

  • make sure every .js file in ui-scripts is now .ts
  • make sure the git history is preserved when the .js to .ts was made
  • make sure only types/imports changed in source files; any other change has a comment explaining why
  • make sure to check Type stripping is enabled by default from v22.18.0 LTS
  • check if test do not do something risky or dangerous (e.g. touching the git repo to push to npm)
  • check if there are files that should have test which now do not have
  • check if there are any 'any' types that should be typed more tightly

TODO:

  • make sure everyone on the team is on at least v22.18.0 Node.js
File Tested? Why not
lib/index.ts Just registers commands
lib/commands/index.ts Just re-exports
lib/commands/bump.ts Real git/npm
lib/commands/tag.ts Real git/npm
lib/commands/deprecate.ts Real git/npm
lib/commands/publish.ts Real git/npm
lib/commands/publish-private.ts Real git/npm
lib/commands/server.ts Needs mocking — spawns http-server
lib/commands/visual-diff.ts
lib/commands/create-component-version.ts
lib/build/babel.ts Needs mocking — spawns babel
lib/build/webpack.ts Needs mocking — spawns webpack
lib/build/clean.ts Modifies real files
lib/build/generate-all-tokens.ts Needs mocking — uses style-dictionary
lib/build/build-themes.ts Just calls other helpers
lib/build/specify-commonjs-format.ts No function to call
lib/build/buildThemes/setupThemes.ts Just calls other helpers
lib/build/buildThemes/generateComponents.ts
lib/build/buildThemes/generatePrimitives.ts
lib/build/buildThemes/generateSemantics.ts
lib/build/buildThemes/createFile.ts
lib/test/lint.ts
lib/utils/git.ts Real git/npm
lib/utils/npm.ts Real git/npm
lib/utils/handle-generate-tokens.ts Needs mocking — uses style-dictionary
lib/utils/handle-map-js-tokens-to-source.ts
lib/utils/addNewExportFileToMetaPackage.ts Modifies real files
lib/utils/addNewExportsEntiresToPackageJSONs.ts Modifies real files
lib/utils/pkg-utils/get-detailed-package-list.ts
lib/utils/pkg-utils/index.ts Just re-exports
lib/icons/build-icons.ts Needs mocking — spawns svgo
lib/icons/svg2jsx.ts
lib/icons/get-glyph-data.ts
lib/icons/generate-icon-fonts.ts Needs mocking — uses fantasticon
lib/icons/generate-legacy-icons-data.ts
lib/icons/generate-react-components.ts
lib/icons/generate-svg-index.ts
lib/icons/generate-custom-index.ts
lib/icons/generate-lucide-index.ts

@ToMESSKa ToMESSKa self-assigned this Jun 3, 2026
@ToMESSKa ToMESSKa force-pushed the INSTUI-5038-convert-ui-scripts-to-type-script branch from 5dc449d to 490034f Compare June 3, 2026 14:21
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://instructure.design/pr-preview/pr-2578/

Built to branch gh-pages at 2026-06-04 11:47 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

github-actions Bot pushed a commit that referenced this pull request Jun 3, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

Visual regression report

No changes.

Status Count
Unchanged 32
Changed 0
New 0
Removed 0

📊 View full report

Baselines come from the visual-baselines branch. They refresh on every merge to master.

* @param bin {string} The binary name, e.g. `pwd`
* @param args {string[]} command arguments
* @param envVars {Object.<string, string>} Environment variables
* @param [envVars] {Object.<string, string>} Environment variables
Copy link
Copy Markdown
Contributor Author

@ToMESSKa ToMESSKa Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

babel.ts calls getCommand(specifyCJSFormat, []) with only 2 arguments — after the TS conversion TypeScript started enforcing the JSDoc that said all 3 args were required, so I marked the 3rd one optional.

/**
* @param [commitIsh] {string}
* @param [allPackages] {any[]}
*/
Copy link
Copy Markdown
Contributor Author

@ToMESSKa ToMESSKa Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npm.ts calls pkgUtils.getChangedPackages() with no arguments — after the TS conversion TypeScript started enforcing the JSDoc that said all 2 args were required, so I marked them optional.


/**
* @param [options] {readPkgUp.NormalizeOptions}
*/
Copy link
Copy Markdown
Contributor Author

@ToMESSKa ToMESSKa Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npm.ts calls pkgUtils.getPackage() with no arguments — after the TS conversion TypeScript started enforcing the JSDoc that said the arg was required, so I marked it optional.

* Reads a package.json
* @param options {readPkgUp.NormalizeOptions}
* @param [options] {readPkgUp.NormalizeOptions}
* @returns {readPkgUp.NormalizedPackageJson}
Copy link
Copy Markdown
Contributor Author

@ToMESSKa ToMESSKa Jun 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump.ts, publish.ts, tag.ts, and deprecate.ts all call pkgUtils.getPackageJSON() with no arguments — after the TS conversion TypeScript started enforcing the JSDoc options as required, so I marked it optional.

* Generates a list of all versioned components based on the @instructure/ui meta package
* Run with: node --experimental-strip-types scripts/generateVersionedExports.ts
* Run with: node scripts/generateVersionedExports.ts
* from the packages/ui-codemods directory.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node 22.18+ can natively run .ts files without the --experimental-strip-types flag, so it was removed it from packages/ui-scripts/lib/index.ts, packages/ui-codemods/package.json, and the packages/ui-codemods/scripts/generateVersionedExports.ts. I also bumped engines.node in the root package.json to >=22.18.0 to enforce the minimum.

"ts:check": "tsc -p tsconfig.build.json --noEmit --emitDeclarationOnly false",
"generate:versioned-exports": "node --experimental-strip-types scripts/generateVersionedExports.ts"
"generate:versioned-exports": "node scripts/generateVersionedExports.ts"
},
Copy link
Copy Markdown
Contributor Author

@ToMESSKa ToMESSKa Jun 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node 22.18+ can natively run .ts files without the --experimental-strip-types flag, so it was removed it from packages/ui-scripts/lib/index.ts, packages/ui-codemods/package.json, and the packages/ui-codemods/scripts/generateVersionedExports.ts. I also bumped engines.node in the root package.json to >=22.18.0 to enforce the minimum.

if (jspaths.length) {
runCommandSync('eslint', jspaths)
runCommandSync('eslint', argv.fix ? [...jspaths, '--fix'] : jspaths)
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --fix option was declared in line 31 but never used, so it was fixed this and tests added.

Comment thread package.json
"engines": {
"node": ">=22",
"node": ">=22.18.0",
"npm": "Use pnpm instead.",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node 22.18+ can natively run .ts files without the --experimental-strip-types flag, so it engines.node so it was bumped >=22.18.0 to enforce the minimum.

runGitCommand(['config', 'user.email', 'instui-dev@instructure.com'])
runGitCommand(['config', 'user.name', 'instructure-ui-ci'])
runGitCommand(['config', 'user.email', EMAIL])
runGitCommand(['config', 'user.name', USERNAME])
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The USERNAME and EMAIL constants were declared at the top of the file but never used and TypeScript flagged them. Connected them to their use sites.

// we could add them as imports from @token-studio/types if needed
case 'boolean':
ret += 'true' | 'false'
ret += "'true' | 'false'"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This showed and error after the TS conversion, I think it was meant to append the string 'true' | 'false' to ret, just like I did for textDecoration one line below, but it did not work. Added a test for this.

const configFile = path.join(process.cwd(), argv.config)
const configFileURL = pathToFileURL(configFile)
const config = await import(configFileURL)
const config = await import(configFileURL.href)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript's dynamic-import() signature only allows string, so after the conversion it errored. I changed it to await import(configFileURL.href) which passes the URL as string.

import readline from 'node:readline/promises'

import pkgUtils from '@instructure/pkg-utils'
import * as pkgUtils from '@instructure/pkg-utils'
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript checked the package's actual .d.ts and errored because there's no default to import.

*/

import pkgUtils from '@instructure/pkg-utils'
import * as pkgUtils from '@instructure/pkg-utils'
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript checked the package's actual .d.ts and errored because there's no default to import.

*/

import pkgUtils from '@instructure/pkg-utils'
import * as pkgUtils from '@instructure/pkg-utils'
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript checked the package's actual .d.ts and errored because there's no default to import.

*/
import semver from 'semver'
import pkgUtils from '@instructure/pkg-utils'
import * as pkgUtils from '@instructure/pkg-utils'
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript checked the package's actual .d.ts and errored because there's no default to import.


import { execSync } from 'node:child_process'
import pkgUtils from '@instructure/pkg-utils'
import * as pkgUtils from '@instructure/pkg-utils'
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript checked the package's actual .d.ts and errored because there's no default to import.

*/

import pkgUtils from '@instructure/pkg-utils'
import * as pkgUtils from '@instructure/pkg-utils'
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript checked the package's actual .d.ts and errored because there's no default to import.

if (error.code !== 'ENOENT') {
if (
!(error instanceof Error && 'code' in error && error.code === 'ENOENT')
) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instanceof Error checks was added because TypeScript was complaining.

error(
`Failed to resolve ${sourceTokens}: ${
err instanceof Error ? err.message : String(err)
}`
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instanceof Error checks was added because TypeScript was complaining.

error(
`Failed to resolve ${outputPackage}: ${
err instanceof Error ? err.message : String(err)
}`
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instanceof Error checks was added because TypeScript was complaining.

}
} catch (e) {
error(e.stack ? e.stack : e)
error(e instanceof Error && e.stack ? e.stack : e)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instanceof Error checks was added because TypeScript was complaining.

@ToMESSKa ToMESSKa force-pushed the INSTUI-5038-convert-ui-scripts-to-type-script branch from 490034f to ac8efca Compare June 4, 2026 11:43
@ToMESSKa ToMESSKa requested review from joyenjoyer and matyasf June 4, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant