Skip to content

Commit 2f0a956

Browse files
committed
feat: 🌟 typegen utils (incomplete)
- add detail to build output - add watch mode to rebuild - add test package with linked deps
1 parent e069e58 commit 2f0a956

26 files changed

+206
-28
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ node_modules
22
yarn.lock
33
yarn-error.log
44
coverage
5+
dist
6+
!test/package/node_modules

README.md

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,47 @@
1-
Centralised config of dev tooling for Nested Code packages.
1+
Centralised tooling config for Nested Code packages.
22

33
---
44

5-
The goal for this project is to support simple and consistent package config across a variety of
6-
platforms and interfaces (CLIs, Node/Deno, browser).
5+
The goal of this project is to support modern, minimal and consistent project scaffolding and
6+
configuration for a variety of environments and targets (CLIs, Node/Deno, browser).
77

8-
One choice I've made to achieve that is to publish exclusively as ES modules (mostly using
9-
Typescript, for Node 14). Narrowing support to ESM (not publishing Common JS) supports not just
10-
simplicity but a forward looking JS ecosystem.
8+
### Entry Points
9+
10+
Distinct bundles can be imported from sub-paths, to be implemented as either:
11+
- **Providers**: where the consumer will have a tool as a dependency and Cogs provides its config.
12+
- **Runners**: where the dependency is not required, Cogs both configures and execute the tool.
1113

12-
[Start here if you're wondering why or how to support ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
14+
Current bundles:
15+
- Jest Provider: `@nested-code/cogs/jest`
16+
- ESBuild Runner: `@nested-code/cogs/esbuild`
17+
- Utils: `@nested-code/cogs/utils` supports interfaces of other bundles.
1318

14-
### Configs
19+
### Features
1520

16-
- [ ] ESBuild script to:
21+
- [ ] ESBuild
1722
- [ ] Lint
1823
- [ ] Build and bundle
1924
- [ ] Write type definitions
2025
- [ ] Update package exports
2126
- [ ] TSConfig
2227
- [ ] ESLint config
2328
- [ ] Jest config
29+
30+
# ES Modules
31+
32+
One choice I've made to achieve that is to publish exclusively as ES modules (mostly using
33+
Typescript, for Node 14). Narrowing support to ESM (not publishing Common JS) supports not just
34+
simplicity but a forward looking JS ecosystem.
35+
36+
[Start here if you're wondering why or how to support
37+
ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
38+
39+
# Learnings
40+
41+
Typescript ES Modules require imports to specify `.js` extensions. Some compilers will handle a
42+
missing extension and infer the path to a matching TS file (tsc) while others use plugins to rewrite
43+
paths (esbuild), but executing directly (ts-node) will still fail.
44+
45+
To overcome this, imports in TS files can use `.js` extension (which is a bit off for my liking)
46+
but there's also an experimental flag `--experimental-specifier-resolution node` that allows no
47+
extension to be given in TS files for importing other TS files.

bin/build.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env node
2+
3+
import { resolve } from 'path'
4+
import esbuild from '../src/esbuild'
5+
import utils from '../src/utils'
6+
7+
console.log(`\n🔨 Building Cogs...`)
8+
9+
const config = esbuild.config({
10+
external: utils.readDependencies(resolve()),
11+
entryPoints: [
12+
'src/esbuild/index.ts',
13+
'src/jest/index.ts',
14+
'src/utils/index.ts'
15+
],
16+
17+
})
18+
19+
utils.clearPath(config.outdir)
20+
esbuild.build(config).then(() => {
21+
utils.typegen(config.entryPoints)
22+
})

esbuild-runner.config.mjs

Lines changed: 0 additions & 8 deletions
This file was deleted.

package.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
{
22
"name": "@nested-code/cogs",
33
"version": "0.0.1",
4-
"description": "Centralised config of dev tooling for Nested Code packages.",
4+
"description": "Centralised tooling config for Nested Code packages.",
55
"repository": "https://github.com/nested-code/cogs",
66
"author": "Tim Kinnane <[email protected]>",
77
"license": "MIT",
88
"private": "false",
99
"type": "module",
1010
"scripts": {
11-
"test": "jest --collectCoverage"
11+
"test": "jest --collectCoverage",
12+
"test:dist": "cd test/package && yarn test",
13+
"build": "node --no-warnings --experimental-specifier-resolution node --loader ts-node/esm bin/build.ts"
1214
},
1315
"dependencies": {
1416
"@types/node": "14",
@@ -26,9 +28,12 @@
2628
"ts-node": "^10.4.0",
2729
"typescript": "^4.5.4"
2830
},
31+
"files": [
32+
"dist"
33+
],
2934
"exports": {
30-
"import": "./esm/index.mjs",
31-
"types": "./dist/index.d.ts",
32-
"utils": "./dist/utils/index.mjs"
35+
"./jest": {
36+
"import": "./dist/jest/index.js"
37+
}
3338
}
3439
}

src/esbuild/build.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { build as _build, analyzeMetafile, BuildOptions } from 'esbuild'
2+
3+
const watch = process.argv.includes('--watch') || process.argv.includes('-w')
4+
5+
/** Build project with Esbuild. */
6+
export const build = async (opts: BuildOptions = {}) =>
7+
_build({
8+
watch: watch
9+
? {
10+
onRebuild: (error, result) => error
11+
? console.error('👀❎ Watch build failed:', error)
12+
: analyzeMetafile(result!.metafile!).then(
13+
(meta) => console.log('👀✅ Watch build succeeded', meta)
14+
)
15+
}
16+
: false,
17+
...opts
18+
})
19+
.then(({ metafile }) => analyzeMetafile(metafile!))
20+
.then(console.log)
21+
.catch(_ => process.exit(1))

src/esbuild/config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { BuildOptions } from 'esbuild'
2+
3+
export type EntryBuildOptions = BuildOptions & Pick<Required<BuildOptions>, 'entryPoints'>
4+
5+
export const defaults: Partial<BuildOptions> = {
6+
minify: false,
7+
sourcemap: true,
8+
format: 'esm',
9+
platform: 'node',
10+
target: 'node14',
11+
outdir: 'dist',
12+
bundle: true,
13+
metafile: true
14+
}
15+
16+
/** Generate ESbuild config, finding dependencies from package. */
17+
export const config = (opts: EntryBuildOptions) =>
18+
({ ...defaults, ...opts })

src/esbuild/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as config from './config'
2+
import * as build from './build'
3+
4+
export const esbuild = {
5+
...config,
6+
...build
7+
}
8+
9+
export default esbuild

src/jest/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import * as config from './config'
1+
import * as cfg from './config'
22

33
export const jest = {
4-
...config
4+
...cfg
55
}
66

77
export default jest

src/utils/clear.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { rmdirSync, mkdirSync } from 'fs'
2+
3+
export const clearPath = (path?: string) => {
4+
if (!path) return
5+
rmdirSync(path, { recursive: true })
6+
mkdirSync(path)
7+
}

0 commit comments

Comments
 (0)