Skip to content

Instantly share code, notes, and snippets.

@lodado
Last active June 13, 2024 12:55
Show Gist options
  • Save lodado/4beb14f44d304fe65772809778e0fb35 to your computer and use it in GitHub Desktop.
Save lodado/4beb14f44d304fe65772809778e0fb35 to your computer and use it in GitHub Desktop.
const fs = require('fs')
const path = require('path')
const readline = require('readline')
const { exec } = require('child_process')
const validatePackageName = (name) => {
const regex = /^@TDS\/[a-zA-Z0-9-_]+$/
if (!regex.test(name)) {
throw new Error(`Invalid package name format. It should be in the format @TDS/package's name`)
}
const hasUppercase = /[A-Z]/.test(name.split('/')[1])
if (hasUppercase) {
console.warn('Warning: Package name should not contain uppercase letters.')
}
}
const generatePackageJson = (packageName, sourcePath) => {
// 무엇인지 인지한 상태에서 바꿀것
const [namespace, name] = packageName.split('/')
const packageJson = {
name: `${namespace}/${name.toLowerCase()}`,
version: '0.0.0',
sideEffects: ['./index.scss'],
license: 'MIT',
exports: {
'.': {
require: sourcePath,
import: sourcePath,
},
'./index.scss': './index.scss',
'./package.json': './package.json',
},
source: sourcePath,
main: sourcePath,
module: sourcePath,
types: sourcePath,
files: ['dist/**'],
scripts: {
test: 'jest --passWithNoTests',
build: 'rollup -c && tsc --emitDeclarationOnly --declarationMap false --declaration --declarationDir dist/types',
lint: `eslint "src/**/*.ts*"`,
clean: `rm -rf .turbo && rm -rf node_modules && rm -rf dist`,
'manual-release': 'pnpm run build && pnpm publish --no-git-checks',
},
devDependencies: {
'@types/node': '^20.12.7',
autoprefixer: '^10.4.19',
'babel-jest': '29.5.0',
eslint: '^8.57.0',
'jest-config': 'workspace:*',
'rollup-config': 'workspace:*',
'eslint-config-acme': 'workspace:*',
postcss: '^8.4.38',
sass: '^1.75.0',
'ts-jest': '29.0.5',
tsconfig: 'workspace:*',
},
dependencies: {},
peerDependencies: {
'@types/react': '^18.2.37',
'@types/react-dom': '^18.2.25',
react: '^16.8 || ^17.0 || ^18.0',
'@TDS/utils': 'workspace:*',
'@TDS/designFiles': 'workspace:*',
},
peerDependenciesMeta: {
'@types/react': {
optional: true,
},
'@types/react-dom': {
optional: true,
},
},
publishConfig: {
access: 'restricted',
registry: 'http://##addressissecret##/api/v4/projects/311/packages/npm/',
exports: {
'.': {
import: {
types: `./dist/types/index.d.ts`,
default: `./dist/es/client/${path.basename(sourcePath).replace('tsx', 'mjs')}`,
},
require: {
types: `./dist/types/index.d.ts`,
default: `./dist/cjs/client/${path.basename(sourcePath).replace('tsx', 'cjs')}`,
},
},
'./index.css': `./dist/es/client/index.css`,
},
source: `./src/index.ts`,
main: `./dist/cjs/client/${path.basename(sourcePath).replace('tsx', 'cjs')}`,
module: `./dist/es/client/${path.basename(sourcePath).replace('tsx', 'mjs')}`,
types: `./dist/types/index.d.ts`,
},
}
return JSON.stringify(packageJson, null, 2)
}
const createSrcIndexTsx = (srcDir) => {
const srcIndexTsxContent = `export {};`
fs.writeFileSync(path.join(srcDir, 'index.tsx'), srcIndexTsxContent)
}
const createRootIndexTsx = (projectDir) => {
const rootIndexTsxContent = `import './index.scss';
// export * from './src';
`
fs.writeFileSync(path.join(projectDir, 'index.tsx'), rootIndexTsxContent)
}
const createEslintConfig = (projectDir) => {
const rootIndexTsxContent = `module.exports = {
root: true,
extends: ["acme"],
};
`
fs.writeFileSync(path.join(projectDir, '.eslintrc.js'), rootIndexTsxContent)
}
const createIndexScss = (projectDir) => {
const indexScssContent = `
`
fs.writeFileSync(path.join(projectDir, 'index.scss'), indexScssContent)
}
const createJestConfig = (projectDir) => {
const jestConfigContent = `const jestConfig = require('jest-config/jest.config.js')
const customJestConfig = {
...jestConfig,
// 패키지별 설정을 여기에 추가
}
module.exports = customJestConfig
`
fs.writeFileSync(path.join(projectDir, 'jest.config.js'), jestConfigContent)
}
const createPostcssConfig = (projectDir) => {
const postcssConfigContent = `module.exports = {
plugins: [require('autoprefixer')()],
}
`
fs.writeFileSync(path.join(projectDir, 'postcss.config.js'), postcssConfigContent)
}
const createRollupConfig = (projectDir) => {
const rollupConfigContent = `import { defaultConfig } from 'rollup-config/rollup.config.mjs'
const config = defaultConfig()
export default config
`
fs.writeFileSync(path.join(projectDir, 'rollup.config.mjs'), rollupConfigContent)
}
const createSetupTests = (projectDir) => {
const setupTestsContent = `import '@testing-library/jest-dom'
`
fs.writeFileSync(path.join(projectDir, 'setupTests.ts'), setupTestsContent)
}
const createTsconfig = (projectDir) => {
const tsconfigContent = `{
"extends": "tsconfig/react-library.json",
"compilerOptions": {
"baseUrl": "./",
"paths": {}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["dist", "build", "node_modules", "**/*.test.*"]
}
`
fs.writeFileSync(path.join(projectDir, 'tsconfig.json'), tsconfigContent)
}
const createProjectStructure = (packageName, projectDir, sourcePath) => {
if (!fs.existsSync(projectDir)) {
fs.mkdirSync(projectDir, { recursive: true })
}
const srcDir = path.join(projectDir, 'src')
if (!fs.existsSync(srcDir)) {
fs.mkdirSync(srcDir)
}
// Write package.json
fs.writeFileSync(path.join(projectDir, 'package.json'), generatePackageJson(packageName, sourcePath))
// Create other files
createSrcIndexTsx(srcDir)
createRootIndexTsx(projectDir)
createIndexScss(projectDir)
createEslintConfig(projectDir)
createJestConfig(projectDir)
createPostcssConfig(projectDir)
createRollupConfig(projectDir)
createSetupTests(projectDir)
createTsconfig(projectDir)
console.log(`Project structure for ${path.basename(projectDir)} created successfully.`)
}
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
})
const question = (text, defaultValue = '') => {
return new Promise((resolve) => {
rl.question(`${text}${defaultValue ? ` (${defaultValue})` : ''}: `, (answer) => resolve(answer || defaultValue))
})
}
const runPnpmInstall = (projectDir) => {
return new Promise((resolve, reject) => {
exec('pnpm install', { cwd: './' }, (error, stdout, stderr) => {
if (error) {
console.error(`Error running pnpm install: ${error}`)
reject(error)
return
}
console.log(stdout)
console.error(stderr)
resolve()
})
})
}
;(async () => {
const packageName = await question('Enter the package name (ex- @TDS/button)')
validatePackageName(packageName)
const folderPath = path.join('./apps/', packageName.replace(/\//g, '-'))
console.log(`folders create in ${folderPath}`)
const sourcePath = './index.tsx'
const projectDir = path.join(folderPath)
console.log(`entryPoint is ${sourcePath}`)
createProjectStructure(packageName, projectDir, sourcePath)
rl.close()
console.log(`package.json generated and project folder created at ${projectDir}.`)
console.log('start installing packages....')
await runPnpmInstall(projectDir)
console.log('done.')
})()
@lodado
Copy link
Author

lodado commented Jun 13, 2024

      '@types/react': '^18.2.37',
      '@types/react-dom': '^18.2.25',
      react: '^16.8 || ^17.0 || ^18.0',
      '@TDS/utils': 'workspace:*',
      '@TDS/designFiles': 'workspace:*',
    },

혹시 사용하실 분은 peerDependencies에 @TDS/utils와 @TDS/designFiles를 제거하시고 사용해주세요. 제가 일하는 곳 내부 레포지토리입니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment