Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FX-4508] Add package extraction script #4039

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
115 changes: 115 additions & 0 deletions bin/extract-packages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
const fs = require('fs')
const path = require('path')

const SOURCE_PATH_TO_EXTRACT = './packages/picasso/src'
const NAMESPACE = '@toptal'
const PACKAGE_PREFIX = 'picasso'

const EXCLUDED_FILES = ['test.ts', 'test.tsx']

const toKebabCase = str =>
str.replace(
/[A-Z]+(?![a-z])|[A-Z]/g,
(match, ofs) => (ofs ? '-' : '') + match.toLowerCase()
)

// Each extracted package will have a name in the format of @toptal/picasso-<folder-name>
const getPackageName = name =>
`${NAMESPACE}/${PACKAGE_PREFIX}-${toKebabCase(name)}`

const processFolder = folderPath => {
const extractedPackageName = getPackageName(path.basename(folderPath))

// Keep track of potential dependencies in all the imports we encounter
const potentialDependencies = new Set()

// Update import paths in TypeScript files
fs.readdirSync(folderPath).forEach(file => {
const filePath = path.join(folderPath, file)

if (
(file.endsWith('.ts') || file.endsWith('.tsx')) &&
!EXCLUDED_FILES.includes(file)
) {
const fileContent = fs.readFileSync(filePath, 'utf-8')
const updatedContent = fileContent.replace(
// Looking for relative imports within the same package
/from\s+'..\/([^']+)'/g,
(_, importName) => {
const packageName = getPackageName(importName)

potentialDependencies.add(packageName)

return `from '${packageName}'`
}
)

// Since we're extracting packages, all external dependencies will be extraneous
// They will still work since they are installed in the root node_modules, but they need to be added later
// @TODO: figure out a way to add them automatically with the same version as in the root package
const contentWithSupressedImportWarning =
'/* eslint-disable import/no-extraneous-dependencies */\n' +
updatedContent

fs.writeFileSync(filePath, contentWithSupressedImportWarning)
}
})

// Create package.json from template
// @TODO: update according to Picasso's structure, i.e. with proper scripts, license, etc.
const packageJson = {
name: extractedPackageName,
version: '1.0.0',
main: 'index.js',
dependencies: Object.fromEntries(
Array.from(potentialDependencies, item => [item, '^1.0.0'])
),
}

fs.writeFileSync(
path.join(folderPath, 'package.json'),
JSON.stringify(packageJson, null, 2)
)

console.log(`Extracted ${folderPath} to ${extractedPackageName}`)

// return the mapping of the folder name to the package name
return [extractedPackageName, folderPath]
}

// Add wildcard package paths for each package, same as we have in tsconfig.json
const addWildcardPackagePath = ([extractedPackageName, folderPath]) => [
[extractedPackageName, [folderPath]],
[`${extractedPackageName}/*`, [`${folderPath}/*`]],
]

// Write the new paths to tsconfig.json to enable TypeScript package resolution
const addTscPaths = newPackagePaths => {
const tsconfigPath = './tsconfig.json'
const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf-8'))

tsconfig.compilerOptions.paths = {
...tsconfig.compilerOptions.paths,
...Object.fromEntries(newPackagePaths),
}

fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2))
// There are two paths for each package, so we divide by 2
console.log(
`Updated ${tsconfigPath} with ${
newPackagePaths.length / 2
} new package paths`
)
}

const newPackagePaths = fs
.readdirSync(SOURCE_PATH_TO_EXTRACT)
.map(folder => path.join(SOURCE_PATH_TO_EXTRACT, folder))
.filter(folderPath => fs.statSync(folderPath).isDirectory())
.map(processFolder)
.map(addWildcardPackagePath)
.flat()

addTscPaths(newPackagePaths)

console.log('Packages created and imports updated successfully.')
9 changes: 5 additions & 4 deletions packages/picasso/src/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type {
ReactNode,
ChangeEvent,
Expand All @@ -10,12 +11,12 @@ import { Accordion as MUIAccordion } from '@material-ui/core'
import type { Theme } from '@material-ui/core/styles'
import { makeStyles } from '@material-ui/core/styles'
import type { StandardProps, TransitionProps } from '@toptal/picasso-shared'
import { ArrowDownMinor16 } from '@toptal/picasso-icon'
import AccordionSummary from '@toptal/picasso-accordion-summary'
import AccordionDetails from '@toptal/picasso-accordion-details'
import ButtonAction from '@toptal/picasso-button-action'

import { ArrowDownMinor16 } from '../Icon'
import AccordionSummary from '../AccordionSummary'
import AccordionDetails from '../AccordionDetails'
import styles from './styles'
import ButtonAction from '../ButtonAction'

export type Borders = 'all' | 'middle' | 'none'

Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/Accordion/Details.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { ReactNode } from 'react'
import React from 'react'
import cx from 'classnames'
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/Accordion/Summary.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { ReactNode } from 'react'
import React from 'react'
import cx from 'classnames'
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/Accordion/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { OmitInternalProps } from '@toptal/picasso-shared'

import type { Props } from './Accordion'
Expand Down
11 changes: 11 additions & 0 deletions packages/picasso/src/Accordion/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "@toptal/picasso-accordion",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@toptal/picasso-icon": "^1.0.0",
"@toptal/picasso-accordion-summary": "^1.0.0",
"@toptal/picasso-accordion-details": "^1.0.0",
"@toptal/picasso-button-action": "^1.0.0"
}
}
1 change: 1 addition & 0 deletions packages/picasso/src/Accordion/styles.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/core/styles'
import { PicassoProvider } from '@toptal/picasso-provider'
Expand Down
3 changes: 2 additions & 1 deletion packages/picasso/src/AccordionCompound/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Accordion, { Details, Summary } from '../Accordion'
/* eslint-disable import/no-extraneous-dependencies */
import Accordion, { Details, Summary } from '@toptal/picasso-accordion'

export const AccordionCompound = Object.assign(Accordion, {
Summary,
Expand Down
8 changes: 8 additions & 0 deletions packages/picasso/src/AccordionCompound/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@toptal/picasso-accordion-compound",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@toptal/picasso-accordion": "^1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { ReactNode, HTMLAttributes } from 'react'
import React from 'react'
import type { Theme } from '@material-ui/core/styles'
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/AccordionDetails/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { OmitInternalProps } from '@toptal/picasso-shared'

import type { Props } from './AccordionDetails'
Expand Down
6 changes: 6 additions & 0 deletions packages/picasso/src/AccordionDetails/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "@toptal/picasso-accordion-details",
"version": "1.0.0",
"main": "index.js",
"dependencies": {}
}
1 change: 1 addition & 0 deletions packages/picasso/src/AccordionDetails/styles.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import { createStyles } from '@material-ui/core/styles'
import { PicassoProvider } from '@toptal/picasso-provider'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { ReactNode, FunctionComponent } from 'react'
import { withStyles } from '@material-ui/core/styles'
import { AccordionSummary as MUIAccordionSummary } from '@material-ui/core'
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/AccordionSummary/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { OmitInternalProps } from '@toptal/picasso-shared'

import type { Props } from './AccordionSummary'
Expand Down
6 changes: 6 additions & 0 deletions packages/picasso/src/AccordionSummary/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "@toptal/picasso-accordion-summary",
"version": "1.0.0",
"main": "index.js",
"dependencies": {}
}
1 change: 1 addition & 0 deletions packages/picasso/src/AccordionSummary/styles.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/core/styles'
import { PicassoProvider } from '@toptal/picasso-provider'
Expand Down
13 changes: 7 additions & 6 deletions packages/picasso/src/AccountSelect/AccountSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { HTMLAttributes } from 'react'
import React, { forwardRef } from 'react'
import type { Theme } from '@material-ui/core/styles'
import { makeStyles } from '@material-ui/core/styles'
import type { BaseProps } from '@toptal/picasso-shared'
import cx from 'classnames'
import UserBadge from '@toptal/picasso-user-badge'
import Typography from '@toptal/picasso-typography'
import { MenuCompound as Menu } from '@toptal/picasso-menu-compound'
import Link from '@toptal/picasso-link'
import Container from '@toptal/picasso-container'
import { ChevronRight16 } from '@toptal/picasso-icon'

import UserBadge from '../UserBadge'
import Typography from '../Typography'
import { MenuCompound as Menu } from '../MenuCompound'
import Link from '../Link'
import Container from '../Container'
import { ChevronRight16 } from '../Icon'
import styles from './styles'

type Account = {
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/AccountSelect/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { OmitInternalProps } from '@toptal/picasso-shared'

import type { Props } from './AccountSelect'
Expand Down
13 changes: 13 additions & 0 deletions packages/picasso/src/AccountSelect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@toptal/picasso-account-select",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@toptal/picasso-user-badge": "^1.0.0",
"@toptal/picasso-typography": "^1.0.0",
"@toptal/picasso-menu-compound": "^1.0.0",
"@toptal/picasso-link": "^1.0.0",
"@toptal/picasso-container": "^1.0.0",
"@toptal/picasso-icon": "^1.0.0"
}
}
1 change: 1 addition & 0 deletions packages/picasso/src/AccountSelect/styles.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/core/styles'

Expand Down
26 changes: 16 additions & 10 deletions packages/picasso/src/Alert/Alert.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { MouseEvent, ReactNode } from 'react'
import React, { forwardRef } from 'react'
import type { Theme } from '@material-ui/core'
import { makeStyles } from '@material-ui/core'
import type { BaseProps } from '@toptal/picasso-shared'
import { SPACING_4 } from '@toptal/picasso-utils'
import type { ButtonProps } from '@toptal/picasso-button'
import type { ButtonSplitProps } from '@toptal/picasso-button-split'
import type { VariantType as ContainerVariants } from '@toptal/picasso-container'
import Container from '@toptal/picasso-container'
import Typography from '@toptal/picasso-typography'
import ButtonCircular from '@toptal/picasso-button-circular'
import {
CloseMinor16,
Exclamation16,
Done16,
Info16,
} from '@toptal/picasso-icon'
import Button from '@toptal/picasso-button'
import ButtonSplit from '@toptal/picasso-button-split'

import { SPACING_4 } from '../utils'
import type { ButtonProps } from '../Button'
import type { ButtonSplitProps } from '../ButtonSplit'
import type { VariantType as ContainerVariants } from '../Container'
import Container from '../Container'
import Typography from '../Typography'
import ButtonCircular from '../ButtonCircular'
import { CloseMinor16, Exclamation16, Done16, Info16 } from '../Icon'
import styles from './styles'
import Button from '../Button'
import ButtonSplit from '../ButtonSplit'

export type VariantType = Extract<
'red' | 'green' | 'yellow' | 'blue',
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/Alert/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { OmitInternalProps } from '@toptal/picasso-shared'

import type { Props } from './Alert'
Expand Down
14 changes: 14 additions & 0 deletions packages/picasso/src/Alert/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "@toptal/picasso-alert",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@toptal/picasso-utils": "^1.0.0",
"@toptal/picasso-button": "^1.0.0",
"@toptal/picasso-button-split": "^1.0.0",
"@toptal/picasso-container": "^1.0.0",
"@toptal/picasso-typography": "^1.0.0",
"@toptal/picasso-button-circular": "^1.0.0",
"@toptal/picasso-icon": "^1.0.0"
}
}
1 change: 1 addition & 0 deletions packages/picasso/src/Alert/styles.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import { createStyles } from '@material-ui/core/styles'

export default () =>
Expand Down
5 changes: 3 additions & 2 deletions packages/picasso/src/AlertCompound/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Alert from '../Alert'
import AlertInline from '../AlertInline'
/* eslint-disable import/no-extraneous-dependencies */
import Alert from '@toptal/picasso-alert'
import AlertInline from '@toptal/picasso-alert-inline'

export const AlertCompound = Object.assign(Alert, {
Inline: AlertInline,
Expand Down
9 changes: 9 additions & 0 deletions packages/picasso/src/AlertCompound/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "@toptal/picasso-alert-compound",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"@toptal/picasso-alert": "^1.0.0",
"@toptal/picasso-alert-inline": "^1.0.0"
}
}
13 changes: 9 additions & 4 deletions packages/picasso/src/AlertInline/AlertInline.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { ReactNode, HTMLAttributes } from 'react'
import React, { forwardRef } from 'react'
import type { BaseProps, ColorType } from '@toptal/picasso-shared'
import type { Theme } from '@material-ui/core'
import { makeStyles } from '@material-ui/core'
import type { VariantType as ContainerVariants } from '@toptal/picasso-container'
import Container from '@toptal/picasso-container'
import Typography from '@toptal/picasso-typography'
import {
ExclamationSolid16,
DoneSolid16,
InfoSolid16,
} from '@toptal/picasso-icon'

import type { VariantType as ContainerVariants } from '../Container'
import Container from '../Container'
import Typography from '../Typography'
import { ExclamationSolid16, DoneSolid16, InfoSolid16 } from '../Icon'
import styles from './styles'

export type VariantType = Extract<
Expand Down
1 change: 1 addition & 0 deletions packages/picasso/src/AlertInline/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable import/no-extraneous-dependencies */
import type { OmitInternalProps } from '@toptal/picasso-shared'

import type { Props } from './AlertInline'
Expand Down
Loading
Loading