Skip to content

Commit

Permalink
Add custom build step using tsc
Browse files Browse the repository at this point in the history
  • Loading branch information
Brendon Boshell committed May 29, 2020
1 parent d092a6c commit eaad4a5
Show file tree
Hide file tree
Showing 8 changed files with 484 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .buildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__snapshots__
stories.tsx
4 changes: 2 additions & 2 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ pipeline:
event: [push]
image: registry.usw.co/cloud/node-12-puppeteer:03228dd2d438979e8973ec16351c4d7bc88f552e
commands:
- npx lerna run build $(npx lerna changed | sed 's/^/--scope /' | tr '\n' ' ') --include-filtered-dependents --include-filtered-dependencies
- npm run build

publish:
when:
branch: master
image: registry.usw.co/cloud/node-12-puppeteer:03228dd2d438979e8973ec16351c4d7bc88f552e
secrets: [ "npm_token" ]
secrets: ['npm_token']
commands:
- npm config set '//registry.npmjs.org/:_authToken' $NPM_TOKEN
- npx lerna publish from-package --yes
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ storybook-static/
lib
lib/*

.storybook/changed.json
.storybook/changed.json
tsconfig.json.*
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
## Development

All commands can be run from individual packages, but it is not necessary to do so.

- Run `npm install` at the project root to install the dev dependencies.
- Run `npx lerna bootstrap` to link package dependencies to each other.

To run storybook locally `npm start`.

To run each package’s build script, run `npx lerna run build`. You don't usually have to do this as you don't need it for local development and the publish script runs it for you on publish.
The packages are all built using the same build step. Run `npm run build` to build all the packages using `tsc`. All files matching `src/**/*.{ts,tsx}` are included and output is written to the `lib` directory within each package.

To add a new element, copy the template to the src/elements directory, update the package.json with the name and add your source code.

## Publishing

To preview which packages have changed, you can run `npx lerna changed` without publishing.

Once happy with the code changes, run `npx lerna version` and bump the versions accordingly.

Lerna will generate a publish commit. Push that commit to your remote branch and once it gets merged to master, CI will publish the new versions to `npm`.

## TODO:

- Make grid columns automatically take space. so 3 columns would automatically render 1/3 on each column, each device by default.
- Make grid s={1/2} auto populate the rest of the sizes. so if you do s={1/2} and leave m and l blank, m and l should also be 1/2
- Generate column sizes based on number of columns and gutter widths.
135 changes: 135 additions & 0 deletions fastbuild.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { readFileSync, writeFileSync } = require('fs')
const path = require('path')

const Project = require('@lerna/project')
const QueryGraph = require('@lerna/query-graph')
const globIgnore = require('glob-gitignore')
const ignore = require('ignore')
const execa = require('execa')
const commonPrefix = require('common-prefix')

const { glob } = globIgnore

const CWD = process.cwd()
const TSCONFIG_FILENAME = 'tsconfig.json'
const IGNORE_FILENAME = '.buildignore'
const OUT_DIR = './lib'
const PACKAGE_GLOB = 'src/**/*.{ts,tsx}'

const tsconfig = () =>
JSON.parse(readFileSync(path.join(CWD, TSCONFIG_FILENAME)))

const buildIgnore = () => {
let rules = ''

try {
rules = readFileSync(path.join(CWD, IGNORE_FILENAME)).toString()
} catch (e) {
if (e.code !== 'ENOENT') {
throw e
}
}

return ignore().add(rules)
}

const splitIterations = async graph => {
let readyPackages = await graph.getAvailablePackages()
const iterations = []

while (readyPackages.length > 0) {
iterations.push(readyPackages)

// Mark these packages as complete on the graph
readyPackages.forEach(package => graph.markAsDone(package))
readyPackages = await graph.getAvailablePackages()
}

return iterations
}

const calcIncludes = location =>
glob([path.relative(CWD, path.join(location, PACKAGE_GLOB))], {
cwd: CWD,
ignore: buildIgnore()
})

const cleanPackages = locations =>
Promise.all([
...locations.map(location =>
execa.command(`rm -rf ${path.join(location, OUT_DIR)}`, {
stdio: 'inherit'
})
),
execa.command(`rm -rf ${path.join(CWD, OUT_DIR)}`, { stdio: 'inherit' })
])

const copyBuiltFiles = async location => {
const includes = await calcIncludes(location)

if (includes.length === 0) {
return
}

const paths = includes.map(include => path.parse(include).dir)
const fromRelative = commonPrefix(paths)
const from = path.join(CWD, OUT_DIR, fromRelative)
const to = path.join(location, OUT_DIR)

return execa.command(`cp -r ${from} ${to}`, { stdio: 'inherit' })
}

const buildIteration = async (iteration, n) => {
const locations = iteration.map(package => package.location)

console.log(`Build iteration ${n}: ${locations.length} packages`)

const filename = `${TSCONFIG_FILENAME}.${n}`
const iterationTsconfig = {
...tsconfig(),
compilerOptions: {
...tsconfig().compilerOptions,
rootDir: CWD,
outDir: OUT_DIR
},
include: (
await Promise.all(locations.map(location => calcIncludes(location)))
).reduce((acc, arr) => acc.concat(arr), [])
}

writeFileSync(
path.join(CWD, filename),
JSON.stringify(iterationTsconfig, null, 4)
)

await execa.command(`npx tsc --project ${filename}`, {
stdio: 'inherit'
})

for (const location of locations) {
await copyBuiltFiles(location)
}
}

const build = async () => {
const project = new Project(CWD)
const packages = await project.getPackages()
const graph = new QueryGraph(packages, {
graphType: 'allDependencies',
rejectCycles: false
})
const locations = packages.map(package => package.location)
const iterations = await splitIterations(graph)

await cleanPackages(locations)

for (let i = 0; i < iterations.length; i++) {
await buildIteration(iterations[i], i)
}
}

build().catch(e => {
console.error(`Build failed: ${String(e)}`)
process.exit(1)
})
Loading

0 comments on commit eaad4a5

Please sign in to comment.