Skip to content

Commit

Permalink
feat(configuration): rename templates and basic workspaces support
Browse files Browse the repository at this point in the history
Import files for build-tool configurations. release-npm
  • Loading branch information
tobua committed Apr 25, 2024
1 parent 4c77597 commit 6a64957
Show file tree
Hide file tree
Showing 16 changed files with 147 additions and 49 deletions.
2 changes: 1 addition & 1 deletion configuration/next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function createFile(configuration: object | string) {
export default next`

if (typeof configuration === 'object') {
if (typeof configuration === 'object' && state.language === 'json') {
contents = `export default ${JSON.stringify(configuration, null, 2)}`
}

Expand Down
18 changes: 10 additions & 8 deletions configuration/playwright.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type { Template } from '../types'
import { fileExtension, state } from '../state'

export const templates: Template<object> = {} // Has no templates, highly customizable.
export const extension = (path: string) => ({ extends: path })

export function createFile() {
return {
name: 'playwright.config.ts',
contents: `import { defineConfig } from '@playwright/test'
import { playwright } from './configuration.ts'
export function createFile(configuration: object | string) {
let contents = `import { playwright } from './configuration.${fileExtension()}'
export default defineConfig(playwright)`,
export default playwright`

if (typeof configuration === 'object' && state.language === 'json') {
contents = `export default ${JSON.stringify(configuration, null, 2)}`
}

return { name: `playwright.config.${fileExtension()}`, contents }
}
4 changes: 2 additions & 2 deletions configuration/rsbuild.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fileExtension } from '../state'
import { fileExtension, state } from '../state'

export const extension = (path: string) => ({ extends: path })

Expand All @@ -7,7 +7,7 @@ export function createFile(configuration: object | string) {
export default rsbuild`

if (typeof configuration === 'object') {
if (typeof configuration === 'object' && state.language === 'json') {
contents = `export default ${JSON.stringify(configuration, null, 2)}`
}

Expand Down
9 changes: 9 additions & 0 deletions configuration/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ export const templates = {
strict: true,
},
},
plugin: {
compilerOptions: {
strict: true,
skipLibCheck: true,
target: 'ES2020',
lib: ['DOM', 'ES2020'],
module: 'Preserve',
},
},
}

export const extension = (path: string) => ({ extends: path })
Expand Down
4 changes: 2 additions & 2 deletions configuration/vite.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fileExtension } from '../state'
import { fileExtension, state } from '../state'

export const extension = (path: string) => ({ extends: path })

Expand All @@ -7,7 +7,7 @@ export function createFile(configuration: object | string) {
export default vite`

if (typeof configuration === 'object') {
if (typeof configuration === 'object' && state.language === 'json') {
contents = `export default ${JSON.stringify(configuration, null, 2)}`
}

Expand Down
9 changes: 8 additions & 1 deletion configuration/vscode.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import type { Template } from '../types'

export const templates: Template<object> = {
recommended: {
biome: {
'editor.defaultFormatter': 'biomejs.biome',
'editor.codeActionsOnSave': {
'quickfix.biome': 'explicit',
'source.organizeImports.biome': 'explicit',
},
'editor.formatOnSave': true,
},
'prettier-eslint': {
'editor.defaultFormatter': 'esbenp.prettier-vscode',
'editor.codeActionsOnSave': {
'source.fixAll.eslint': true,
},
'editor.formatOnSave': true,
},
}

export function createFile(configuration: object) {
Expand Down
34 changes: 25 additions & 9 deletions helper.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { existsSync } from 'node:fs'
import { join } from 'node:path'
import { existsSync, lstatSync } from 'node:fs'
import { it } from 'avait'
import Bun from 'bun'
import Bun, { Glob } from 'bun'
import { create } from 'logua'
import { parse } from 'parse-gitignore'
import { z } from 'zod'
import { configurations, ignore } from './configuration'
import { state } from './state'
import { root, state } from './state'

export const log = create('zero-configuration', 'blue')

export const root = (file: string) =>
process.cwd().includes('node_modules') ? join(process.cwd(), '../..', file) : join(process.cwd(), file)

const keys = Object.fromEntries(configurations.map((current) => [current.name, z.union([z.string(), z.object({}), z.boolean()])]))

for (const configuration of configurations) {
Expand Down Expand Up @@ -84,11 +80,31 @@ export async function writeGitIgnore(ignores: string[]) {

const file = ignore.createFile(userIgnores as string[])

if (existsSync(file.name)) {
if (existsSync(root(file.name))) {
await addAdditionalGitignoreEntries(file)
} else {
} else if (state.root) {
await Bun.write(root(file.name), file.contents)
}

return Object.hasOwn(state.options, 'ignore') || Object.hasOwn(state.options, 'gitignore')
}

export async function getWorkspaces() {
const packageJson = await Bun.file(root('./package.json')).json()
const workspaces: { path: string; root: boolean }[] = []

if (Array.isArray(packageJson.workspaces)) {
for (const workspaceGlob of packageJson.workspaces) {
const glob = new Glob(workspaceGlob)
for await (const file of glob.scan({ cwd: root('/'), dot: false, onlyFiles: false })) {
if (lstatSync(file).isDirectory()) {
workspaces.push({ path: file, root: false })
}
}
}
}

workspaces.push({ path: '/', root: true }) // Always run in root, root should run last.

return workspaces
}
37 changes: 22 additions & 15 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
#!/usr/bin/env bun
import Bun from 'bun'
import { configurations } from './configuration'
import { findConfiguration, log, root, writeGitIgnore } from './helper'
import { findConfiguration, getWorkspaces, log, writeGitIgnore } from './helper'
import { parse } from './parse'
import { state } from './state'
import { reset, root, state } from './state'

const ignores: string[] = []
async function configureProject() {
const ignores: string[] = []

await findConfiguration()
await findConfiguration()

for (const { name, alias, configuration } of configurations) {
const value = state.options[name] ?? (alias && state.options[alias])
if (!value) continue
const file = await parse(value, configuration)
if (!file) continue
await Bun.write(root(file.name), file.contents)
ignores.push(file.name)
}
for (const { name, alias, configuration } of configurations) {
const value = state.options[name] ?? (alias && state.options[alias])
if (!value) continue
const file = await parse(value, configuration)
if (!file) continue
await Bun.write(root(file.name), file.contents)
ignores.push(file.name)
}

const gitUserConfigured = await writeGitIgnore(ignores)

const gitUserConfigured = await writeGitIgnore(ignores)
if (!gitUserConfigured && ignores.length === 0) {
log('No configuration to add', 'warning')
}
}

if (!gitUserConfigured && ignores.length === 0) {
log('No configuration to add', 'warning')
for (const workspace of await getWorkspaces()) {
reset(workspace)
await configureProject()
}
22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@
"bun.lockb",
"test/fixture/*/*",
"!test/fixture/*/package.json",
"!test/fixture/workspaces/package.json",
"!test/fixture/workspaces/plugin",
"test/fixture/workspaces/plugin/*",
"!test/fixture/workspaces/plugin/package.json",
"!test/fixture/workspaces/demo",
"test/fixture/workspaces/demo/*",
"!test/fixture/workspaces/demo/react",
"test/fixture/workspaces/demo/react/*",
"!test/fixture/workspaces/demo/react/package.json",
"!test/fixture/*/configuration.ts",
"!test/fixture/*/configuration.js"
],
Expand All @@ -70,18 +79,9 @@
]
}
},
"vscode": "recommended",
"vscode": "biome",
"typescript": {
"compilerOptions": {
"strict": true,
"skipLibCheck": true,
"target": "ES2020",
"lib": [
"DOM",
"ES2020"
],
"module": "Preserve"
},
"extends": "plugin",
"files": [
"index.ts"
]
Expand Down
5 changes: 5 additions & 0 deletions parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { existsSync } from 'node:fs'
import { join } from 'node:path'
import { it } from 'avait'
import { merge } from 'ts-deepmerge'
import { state } from './state'
import type { Configuration, Options } from './types'

const isExtension = async (value: string) => {
Expand Down Expand Up @@ -56,6 +57,10 @@ export async function parse(value: Options, configuration: Configuration['config
return configuration.createFile()
}

if (typeof value === 'object' && state.language !== 'json') {
return configuration.createFile(value)
}

// biome-ignore lint/style/noParameterAssign: Easier in this case.
value = extendTemplate(value, configuration)

Expand Down
14 changes: 14 additions & 0 deletions state.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { join } from 'node:path'
import type { State } from './types'

export const state: State = {
options: {},
language: 'json',
packageJson: { name: 'missing-package-name' },
directory: '/',
root: true,
}

export const fileExtension = () => (state.language === 'javascript' ? 'js' : 'ts')

export const root = (file: string) =>
process.cwd().includes('node_modules') ? join(process.cwd(), '../..', state.directory, file) : join(process.cwd(), state.directory, file)

export const reset = ({ path, root }: { path: string; root: boolean }) => {
state.options = {}
state.language = 'json'
state.packageJson = { name: 'missing-package-name' }
state.directory = path
state.root = root
}
13 changes: 13 additions & 0 deletions test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,16 @@ test('Creates configuration files for various build-tool configurations.', () =>
expect(existsSync(join(fixturePath, 'rsbuild.config.ts'))).toBe(true)
expect(existsSync(join(fixturePath, 'vite.config.ts'))).toBe(true)
})

test('Creates configuration files in all workspaces including the root.', () => {
const fixturePath = './test/fixture/workspaces'

execSync('bun ./../../../index.ts', {
cwd: fixturePath,
stdio: 'inherit',
})

expect(existsSync(join(fixturePath, 'tsconfig.json'))).toBe(true)
expect(existsSync(join(fixturePath, 'demo/react/tsconfig.json'))).toBe(true)
expect(existsSync(join(fixturePath, 'plugin/tsconfig.json'))).toBe(true)
})
7 changes: 7 additions & 0 deletions test/fixture/workspaces/demo/react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "demo-react",
"configuration": {
"typescript": "plugin",
"vite": true
}
}
10 changes: 10 additions & 0 deletions test/fixture/workspaces/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "workspaces",
"workspaces": [
"demo/*",
"plugin"
],
"configuration": {
"typescript": "plugin"
}
}
6 changes: 6 additions & 0 deletions test/fixture/workspaces/plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "plugin",
"configuration": {
"typescript": "plugin"
}
}
2 changes: 2 additions & 0 deletions types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ export interface State {
// configuration.js: JavaScript, configuration.ts: TypeScript
language: 'json' | 'javascript' | 'typescript'
packageJson: PackageJson
directory: string
root: boolean
}

0 comments on commit 6a64957

Please sign in to comment.