@marcuth/create-package 0.1.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # @marcuth/create-package
2
+
3
+ A personalized CLI tool to quickly bootstrap a new TypeScript package with a predefined set of best practices and tools.
4
+
5
+ ## ✨ Features
6
+
7
+ - **TypeScript Ready**: Pre-configured `tsconfig.json` for modern Node.js development.
8
+ - **ESLint & Prettier**: Full linting setup including `eslint-plugin-unused-imports` and automatic code formatting.
9
+ - **Git Integration**: Automatically initializes a git repository, prompts for a remote origin, and sets up `.gitignore` and `.gitattributes`.
10
+ - **Package Metadata**: Infers `homepage` and `bugs` URLs from your repository link (GitHub/GitLab).
11
+ - **Package Manager Detection**: Intelligently detects whether you are using `npm`, `pnpm`, or `yarn`.
12
+
13
+ ## 🚀 Usage
14
+
15
+ You can run it directly npm:
16
+
17
+ ```bash
18
+ npm create @marcuth/package@latest my-package # or npm init @marcuth/package@latest my-package
19
+ ```
20
+
21
+ Or for scoped packages:
22
+
23
+ ```bash
24
+ npm create @marcuth/package@latest @scope/my-package # or npm init @marcuth/package@latest @scope/my-package
25
+ ```
26
+
27
+ ## 🛠️ What's Inside the Generated Project?
28
+
29
+ - **Standard Directory Structure**: `src/` directory for your TypeScript source code.
30
+ - **Pre-configured Scripts**:
31
+ - `npm run build`: Compiles TypeScript to `dist/`.
32
+ - `npm run dev`: Runs the project using `ts-node`.
33
+ - `npm run format`: Formats code using Prettier.
34
+ - `npm run lint`: Checks for linting errors and removes unused imports.
35
+ - **Standard Files**: `.gitignore`, `.gitattributes`, `LICENSE` (MIT), `README.md`, and `.npmignore`.
36
+
37
+ ## 📦 Requirements
38
+
39
+ - Node.js installed.
40
+ - Git (optional, but recommended for repository initialization).
41
+
42
+ ## 📄 License
43
+
44
+ MIT © [Marcuth](https://github.com/marcuth)
package/bin/index.js CHANGED
@@ -1,460 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from "fs"
4
- import path from "path"
5
- import { spawnSync } from "child_process"
3
+ import { main } from "../src/index.js"
6
4
 
7
- function getInputName() {
8
- return process.argv[2] || "my-package"
9
- }
10
-
11
- function parsePackageName(inputName) {
12
- if (inputName.startsWith("@")) {
13
- if (!inputName.includes("/")) {
14
- console.error("❌ Invalid scope. Use @scope/name")
15
- process.exit(1)
16
- }
17
-
18
- const [, name] = inputName.split("/")
19
- return {
20
- packageName: inputName,
21
- projectDir: name
22
- }
23
- }
24
-
25
- return {
26
- packageName: inputName,
27
- projectDir: inputName
28
- }
29
- }
30
-
31
- function createDirectories(root) {
32
- fs.mkdirSync(root, { recursive: true })
33
- fs.mkdirSync(path.join(root, "src"))
34
- }
35
-
36
- function writePackageJson(root, packageName) {
37
- const content = {
38
- name: packageName,
39
- version: "0.1.0",
40
- type: "commonjs",
41
- main: "./dist/index.js",
42
- module: "./dist/index.js",
43
- types: "./dist/index.d.ts",
44
- files: [
45
- "dist/*",
46
- "!/**/__tests__"
47
- ],
48
- scripts: {
49
- build: "tsc",
50
- dev: "ts-node ./src/index.ts",
51
- format: "prettier --write \"src/**/*.ts\""
52
- },
53
- publishConfig: {
54
- access: "public"
55
- },
56
- keywords: [
57
- "marcuth"
58
- ],
59
- author: "Marcuth",
60
- license: "MIT"
61
- }
62
-
63
- fs.writeFileSync(
64
- path.join(root, "package.json"),
65
- JSON.stringify(content, null, 2)
66
- )
67
- }
68
-
69
- function writeTsConfig(root) {
70
- const content = {
71
- "compilerOptions": {
72
- "target": "es2019",
73
- "lib": ["ES2015"],
74
- "module": "NodeNext",
75
- "esModuleInterop": true,
76
- "forceConsistentCasingInFileNames": true,
77
- "strict": true,
78
- "skipLibCheck": true,
79
- "outDir": "./dist",
80
- "rootDir": "./src",
81
- "declaration": true,
82
- "declarationMap": false,
83
- },
84
- "include": ["src"],
85
- "exclude": ["node_modules", "dist"]
86
- }
87
-
88
-
89
- fs.writeFileSync(
90
- path.join(root, "tsconfig.json"),
91
- JSON.stringify(content, null, 2)
92
- )
93
- }
94
-
95
- function writeSourceFile(root, projectDir) {
96
- const content = `function main() {
97
- console.log("Hello from ${projectDir}")
98
- }
99
-
100
- main()
101
- `
102
-
103
- fs.writeFileSync(
104
- path.join(root, "src/index.ts"),
105
- content
106
- )
107
- }
108
-
109
- function writeLicenseFile(root) {
110
- const currentYear = new Date().getFullYear()
111
-
112
- const content = `MIT License
113
-
114
- Copyright (c) ${currentYear} Marcuth
115
-
116
- Permission is hereby granted, free of charge, to any person obtaining a copy
117
- of this software and associated documentation files (the "Software"), to deal
118
- in the Software without restriction, including without limitation the rights
119
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
120
- copies of the Software, and to permit persons to whom the Software is
121
- furnished to do so, subject to the following conditions:
122
-
123
- The above copyright notice and this permission notice shall be included in all
124
- copies or substantial portions of the Software.
125
-
126
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
127
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
128
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
129
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
130
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
131
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
132
- SOFTWARE.`
133
-
134
- fs.writeFileSync(
135
- path.join(root, "LICENSE"),
136
- content
137
- )
138
- }
139
-
140
- function writeGitignoreFile(root) {
141
- const content = `# Created by https://www.toptal.com/developers/gitignore/api/node
142
- # Edit at https://www.toptal.com/developers/gitignore?templates=node
143
-
144
- ### Node ###
145
- # Logs
146
- dist/
147
- logs
148
- *.log
149
- npm-debug.log*
150
- yarn-debug.log*
151
- yarn-error.log*
152
- lerna-debug.log*
153
- .pnpm-debug.log*
154
-
155
- # Diagnostic reports (https://nodejs.org/api/report.html)
156
- report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
157
-
158
- # Runtime data
159
- pids
160
- *.pid
161
- *.seed
162
- *.pid.lock
163
-
164
- # Directory for instrumented libs generated by jscoverage/JSCover
165
- lib-cov
166
-
167
- # Coverage directory used by tools like istanbul
168
- coverage
169
- *.lcov
170
-
171
- # nyc test coverage
172
- .nyc_output
173
-
174
- # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
175
- .grunt
176
-
177
- # Bower dependency directory (https://bower.io/)
178
- bower_components
179
-
180
- # node-waf configuration
181
- .lock-wscript
182
-
183
- # Compiled binary addons (https://nodejs.org/api/addons.html)
184
- build/Release
185
-
186
- # Dependency directories
187
- node_modules/
188
- jspm_packages/
189
-
190
- # Snowpack dependency directory (https://snowpack.dev/)
191
- web_modules/
192
-
193
- # TypeScript cache
194
- *.tsbuildinfo
195
-
196
- # Optional npm cache directory
197
- .npm
198
-
199
- # Optional eslint cache
200
- .eslintcache
201
-
202
- # Optional stylelint cache
203
- .stylelintcache
204
-
205
- # Microbundle cache
206
- .rpt2_cache/
207
- .rts2_cache_cjs/
208
- .rts2_cache_es/
209
- .rts2_cache_umd/
210
-
211
- # Optional REPL history
212
- .node_repl_history
213
-
214
- # Output of 'npm pack'
215
- *.tgz
216
-
217
- # Yarn Integrity file
218
- .yarn-integrity
219
-
220
- # dotenv environment variable files
221
- .env
222
- .env.development.local
223
- .env.test.local
224
- .env.production.local
225
- .env.local
226
-
227
- # parcel-bundler cache (https://parceljs.org/)
228
- .cache
229
- .parcel-cache
230
-
231
- # Next.js build output
232
- .next
233
- out
234
-
235
- # Nuxt.js build / generate output
236
- .nuxt
237
- dist
238
-
239
- # Gatsby files
240
- .cache/
241
- # Comment in the public line in if your project uses Gatsby and not Next.js
242
- # https://nextjs.org/blog/next-9-1#public-directory-support
243
- # public
244
-
245
- # vuepress build output
246
- .vuepress/dist
247
-
248
- # vuepress v2.x temp and cache directory
249
- .temp
250
-
251
- # Docusaurus cache and generated files
252
- .docusaurus
253
-
254
- # Serverless directories
255
- .serverless/
256
-
257
- # FuseBox cache
258
- .fusebox/
259
-
260
- # DynamoDB Local files
261
- .dynamodb/
262
-
263
- # TernJS port file
264
- .tern-port
265
-
266
- # Stores VSCode versions used for testing VSCode extensions
267
- .vscode-test
268
-
269
- # yarn v2
270
- .yarn/cache
271
- .yarn/unplugged
272
- .yarn/build-state.yml
273
- .yarn/install-state.gz
274
- .pnp.*
275
-
276
- ### Node Patch ###
277
- # Serverless Webpack directories
278
- .webpack/
279
-
280
- # Optional stylelint cache
281
-
282
- # SvelteKit build / generate output
283
- .svelte-kit
284
-
285
- # End of https://www.toptal.com/developers/gitignore/api/node`
286
-
287
- fs.writeFileSync(
288
- path.join(root, ".gitignore"),
289
- content
290
- )
291
- }
292
-
293
- function createNpmIgnore(root) {
294
- const content = `src/
295
- tsconfig.json`
296
-
297
- fs.writeFileSync(
298
- path.join(root, ".npmignore"),
299
- content
300
- )
301
- }
302
-
303
- function createReadme(root, packageName) {
304
- const content = `# ${packageName}`
305
-
306
- fs.writeFileSync(
307
- path.join(root, "README.md"),
308
- content
309
- )
310
- }
311
-
312
- function createEsLintRcConfig(root) {
313
- const content = {
314
- "extends": [
315
- "plugin:prettier/recommended"
316
- ],
317
- "plugins": [
318
- "prettier"
319
- ],
320
- "rules": {
321
- "prettier/prettier": "error"
322
- }
323
- }
324
-
325
- fs.writeFileSync(
326
- path.join(root, ".eslintrc.json"),
327
- JSON.stringify(content, null, 4)
328
- )
329
- }
330
-
331
- function createPrettierConfig(root) {
332
- const content = `module.exports = {
333
- "semi": false,
334
- "singleQuote": false,
335
- "tabWidth": 4,
336
- "useTabs": false,
337
- "importTypeOrder": ["NPMPackages", "localImports"],
338
- "newlineBetweenTypes": true,
339
- "sortingMethod": "lineLength",
340
- "plugins": ["./node_modules/prettier-plugin-sort-imports/dist/index.js"],
341
- "endOfLine": "auto",
342
- "printWidth": 120
343
- }`
344
-
345
- fs.writeFileSync(
346
- path.join(root, ".prettierrc.js"),
347
- content
348
- )
349
- }
350
-
351
- function detectPackageManager() {
352
- const userAgent = process.env.npm_config_user_agent || ""
353
-
354
- if (userAgent.includes("pnpm")) return "pnpm"
355
- if (userAgent.includes("yarn")) return "yarn"
356
-
357
- return "npm"
358
- }
359
-
360
- function installDevDependencies(root, deps) {
361
- const pm = detectPackageManager()
362
-
363
- const commands = {
364
- npm: ["install", "--save-dev", ...deps],
365
- pnpm: ["add", "-D", ...deps],
366
- yarn: ["add", "-D", ...deps]
367
- }
368
-
369
- console.log("📦 Installing dev dependencies using", pm)
370
- console.log("📦 Command:", pm, commands[pm].join(" "))
371
-
372
- const result = spawnSync(pm, commands[pm], {
373
- cwd: root,
374
- stdio: "inherit",
375
- shell: true
376
- })
377
-
378
- if (result.error) {
379
- console.error("❌ Spawn error:", result.error)
380
- process.exit(1)
381
- }
382
-
383
- if (result.status !== 0) {
384
- console.error("❌ Failed to install dev dependencies")
385
- process.exit(1)
386
- }
387
- }
388
-
389
- function hasGit() {
390
- const result = spawnSync("git", ["--version"], { stdio: "ignore" })
391
- return result.status === 0
392
- }
393
-
394
- function initGitRepo(root) {
395
- if (!hasGit()) {
396
- console.log("⚠️ Git not found, skipping git init")
397
- return
398
- }
399
-
400
- console.log("🌱 Initializing git repository")
401
-
402
- const result = spawnSync(
403
- "git",
404
- ["init"],
405
- {
406
- cwd: root,
407
- stdio: "inherit"
408
- }
409
- )
410
-
411
- if (result.status !== 0) {
412
- console.error("❌ Falha ao inicializar git")
413
- process.exit(1)
414
- }
415
- }
416
-
417
- function createInitialCommit(root) {
418
- console.log("📸 Creating initial commit")
419
-
420
- spawnSync("git", ["add", "."], {
421
- cwd: root,
422
- stdio: "inherit"
423
- })
424
-
425
- spawnSync(
426
- "git",
427
- ["commit", "-m", "chore: initial commit"],
428
- {
429
- cwd: root,
430
- stdio: "inherit"
431
- }
432
- )
433
- }
434
-
435
- function main() {
436
- const inputName = getInputName()
437
- const { packageName, projectDir } = parsePackageName(inputName)
438
- const root = path.resolve(process.cwd(), projectDir)
439
- const devDependencies = ["@types/node", "ts-node", "typescript", "prettier", "prettier-plugin-sort-imports", "eslint", "eslint-config-prettier", "eslint-plugin-prettier"]
440
-
441
- createDirectories(root)
442
- writePackageJson(root, packageName)
443
- writeTsConfig(root)
444
- writeSourceFile(root, projectDir)
445
- writeLicenseFile(root)
446
- writeGitignoreFile(root)
447
- installDevDependencies(root, devDependencies)
448
- initGitRepo(root)
449
- createNpmIgnore(root)
450
- createReadme(root, packageName)
451
- createEsLintRcConfig(root)
452
- createPrettierConfig(root)
453
- createInitialCommit(root)
454
-
455
- console.log("✅ Creeated project")
456
- console.log("📦 Package:", packageName)
457
- console.log("📁 Folder:", projectDir)
458
- }
459
-
460
- main()
5
+ main().catch(err => {
6
+ console.error("❌ Unexpected error:", err)
7
+ process.exit(1)
8
+ })
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@marcuth/create-package",
3
- "version": "0.1.3",
3
+ "version": "0.3.0",
4
4
  "description": "Create a new package",
5
- "main": "index.js",
5
+ "main": "bin/index.js",
6
6
  "type": "module",
7
+ "files": [
8
+ "bin",
9
+ "src"
10
+ ],
7
11
  "bin": {
8
12
  "create-package": "./bin/index.js"
9
13
  },
package/src/index.js ADDED
@@ -0,0 +1,67 @@
1
+ import path from "node:path"
2
+ import readline from "node:readline/promises"
3
+ import { getInputName, parsePackageName } from "./input.js"
4
+ import {
5
+ createDirectories,
6
+ writePackageJson,
7
+ writeTsConfig,
8
+ writeSourceFile,
9
+ writeLicenseFile,
10
+ writeGitignoreFile,
11
+ writeGitAttributes,
12
+ createNpmIgnore,
13
+ createReadme,
14
+ createEsLintRcConfig,
15
+ createPrettierConfig,
16
+ writeTestFile
17
+ } from "./writers.js"
18
+ import { installDevDependencies, initGitRepo, createInitialCommit } from "./system.js"
19
+
20
+ export async function main() {
21
+ const inputName = getInputName()
22
+ const { packageName, projectDir } = parsePackageName(inputName)
23
+ const root = path.resolve(process.cwd(), projectDir)
24
+
25
+ const rl = readline.createInterface({
26
+ input: process.stdin,
27
+ output: process.stdout
28
+ })
29
+
30
+ const repoUrl = await rl.question("🔗 Repository URL (optional): ")
31
+
32
+ rl.close()
33
+
34
+ const devDependencies = [
35
+ "@types/node",
36
+ "ts-node",
37
+ "typescript",
38
+ "prettier",
39
+ "prettier-plugin-sort-imports",
40
+ "eslint",
41
+ "eslint-config-prettier",
42
+ "eslint-plugin-prettier",
43
+ "eslint-plugin-unused-imports",
44
+ "vitest",
45
+ "@vitest/coverage-v8"
46
+ ]
47
+
48
+ createDirectories(root)
49
+ writePackageJson(root, packageName, repoUrl)
50
+ writeTsConfig(root)
51
+ writeSourceFile(root, projectDir)
52
+ writeLicenseFile(root)
53
+ writeGitignoreFile(root)
54
+ writeGitAttributes(root)
55
+ installDevDependencies(root, devDependencies)
56
+ initGitRepo(root, repoUrl)
57
+ createNpmIgnore(root)
58
+ createReadme(root, packageName)
59
+ createEsLintRcConfig(root)
60
+ createPrettierConfig(root)
61
+ writeTestFile(root)
62
+ createInitialCommit(root)
63
+
64
+ console.log("✅ Creeated project")
65
+ console.log("📦 Package:", packageName)
66
+ console.log("📁 Folder:", projectDir)
67
+ }
package/src/input.js ADDED
@@ -0,0 +1,24 @@
1
+ export function getInputName() {
2
+ return process.argv[2] || "my-package"
3
+ }
4
+
5
+ export function parsePackageName(inputName) {
6
+ if (inputName.startsWith("@")) {
7
+ if (!inputName.includes("/")) {
8
+ console.error("❌ Invalid scope. Use @scope/name")
9
+ process.exit(1)
10
+ }
11
+
12
+ const [, name] = inputName.split("/")
13
+
14
+ return {
15
+ packageName: inputName,
16
+ projectDir: name
17
+ }
18
+ }
19
+
20
+ return {
21
+ packageName: inputName,
22
+ projectDir: inputName
23
+ }
24
+ }
package/src/system.js ADDED
@@ -0,0 +1,92 @@
1
+ import { spawnSync } from "node:child_process"
2
+
3
+ export function detectPackageManager() {
4
+ const userAgent = process.env.npm_config_user_agent || ""
5
+
6
+ if (userAgent.includes("pnpm")) return "pnpm"
7
+ if (userAgent.includes("yarn")) return "yarn"
8
+
9
+ return "npm"
10
+ }
11
+
12
+ export function installDevDependencies(root, deps) {
13
+ const pm = detectPackageManager()
14
+
15
+ const commands = {
16
+ npm: ["install", "--save-dev", ...deps],
17
+ pnpm: ["add", "-D", ...deps],
18
+ yarn: ["add", "-D", ...deps]
19
+ }
20
+
21
+ console.log("📦 Installing dev dependencies using", pm)
22
+ console.log("📦 Command:", pm, commands[pm].join(" "))
23
+
24
+ const result = spawnSync(pm, commands[pm], {
25
+ cwd: root,
26
+ stdio: "inherit",
27
+ shell: true
28
+ })
29
+
30
+ if (result.error) {
31
+ console.error("❌ Spawn error:", result.error)
32
+ process.exit(1)
33
+ }
34
+
35
+ if (result.status !== 0) {
36
+ console.error("❌ Failed to install dev dependencies")
37
+ process.exit(1)
38
+ }
39
+ }
40
+
41
+ export function hasGit() {
42
+ const result = spawnSync("git", ["--version"], { stdio: "ignore" })
43
+ return result.status === 0
44
+ }
45
+
46
+ export function initGitRepo(root, repoUrl = "") {
47
+ if (!hasGit()) {
48
+ console.log("⚠️ Git not found, skipping git init")
49
+ return
50
+ }
51
+
52
+ console.log("🌱 Initializing git repository")
53
+
54
+ spawnSync(
55
+ "git",
56
+ ["init"],
57
+ {
58
+ cwd: root,
59
+ stdio: "inherit"
60
+ }
61
+ )
62
+
63
+ if (repoUrl) {
64
+ console.log("🔗 Setting remote origin:", repoUrl)
65
+ spawnSync(
66
+ "git",
67
+ ["remote", "add", "origin", repoUrl],
68
+ {
69
+ cwd: root,
70
+ stdio: "inherit"
71
+ }
72
+ )
73
+ }
74
+ }
75
+
76
+ export function createInitialCommit(root) {
77
+ console.log("📸 Creating initial commit")
78
+
79
+ spawnSync("git", ["add", "."], {
80
+ cwd: root,
81
+ stdio: "inherit"
82
+ })
83
+
84
+ spawnSync(
85
+ "git",
86
+ ["commit", "-m", "chore: initial commit"],
87
+ {
88
+ cwd: root,
89
+ stdio: "inherit"
90
+ }
91
+ )
92
+ }
package/src/writers.js ADDED
@@ -0,0 +1,377 @@
1
+ import fs from "node:fs"
2
+ import path from "node:path"
3
+
4
+ export function createDirectories(root) {
5
+ fs.mkdirSync(root, { recursive: true })
6
+ fs.mkdirSync(path.join(root, "src"))
7
+ fs.mkdirSync(path.join(root, "__tests__"))
8
+ }
9
+
10
+ export function writePackageJson(root, packageName, repoUrl = "") {
11
+ let homepage = undefined
12
+ let bugs = undefined
13
+
14
+ if (repoUrl) {
15
+ const baseUrl = repoUrl.replace(/\.git$/, "")
16
+
17
+ if (repoUrl.includes("github.com") || repoUrl.includes("gitlab.com")) {
18
+ homepage = `${baseUrl}#readme`
19
+ bugs = {
20
+ url: `${baseUrl}/issues`
21
+ }
22
+ }
23
+ }
24
+
25
+ const content = {
26
+ name: packageName,
27
+ version: "0.1.0",
28
+ type: "commonjs",
29
+ repository: repoUrl ? {
30
+ type: "git",
31
+ url: repoUrl
32
+ } : undefined,
33
+ homepage,
34
+ bugs,
35
+ main: "./dist/index.js",
36
+ module: "./dist/index.js",
37
+ types: "./dist/index.d.ts",
38
+ files: [
39
+ "dist/*",
40
+ "!/**/__tests__"
41
+ ],
42
+ scripts: {
43
+ build: "tsc",
44
+ dev: "ts-node ./src/index.ts",
45
+ format: "prettier --write \"src/**/*.ts\"",
46
+ lint: "eslint \"src/**/*.ts\" --fix",
47
+ test: "vitest",
48
+ "test:cov": "vitest run --coverage"
49
+ },
50
+ publishConfig: {
51
+ access: "public"
52
+ },
53
+ keywords: [
54
+ "marcuth"
55
+ ],
56
+ author: "Marcuth",
57
+ license: "MIT"
58
+ }
59
+
60
+ fs.writeFileSync(
61
+ path.join(root, "package.json"),
62
+ JSON.stringify(content, null, 2)
63
+ )
64
+ }
65
+
66
+ export function writeTsConfig(root) {
67
+ const content = {
68
+ "compilerOptions": {
69
+ "target": "es2019",
70
+ "lib": ["ES2015"],
71
+ "module": "NodeNext",
72
+ "esModuleInterop": true,
73
+ "forceConsistentCasingInFileNames": true,
74
+ "strict": true,
75
+ "skipLibCheck": true,
76
+ "outDir": "./dist",
77
+ "rootDir": "./src",
78
+ "declaration": true,
79
+ "declarationMap": false,
80
+ },
81
+ "include": ["src"],
82
+ "exclude": ["node_modules", "dist"]
83
+ }
84
+
85
+ fs.writeFileSync(
86
+ path.join(root, "tsconfig.json"),
87
+ JSON.stringify(content, null, 2)
88
+ )
89
+ }
90
+
91
+ export function writeSourceFile(root, projectDir) {
92
+ const content = `export function main() {
93
+ console.log("Hello from ${projectDir}")
94
+ }
95
+
96
+ main()
97
+ `
98
+
99
+ fs.writeFileSync(
100
+ path.join(root, "src/index.ts"),
101
+ content
102
+ )
103
+ }
104
+
105
+ export function writeTestFile(root) {
106
+ const content = `import { expect, test } from "vitest"
107
+ import { main } from "../src/index"
108
+
109
+ test("main should be a function", () => {
110
+ expect(typeof main).toBe("function")
111
+ })
112
+ `
113
+
114
+ fs.writeFileSync(
115
+ path.join(root, "__tests__/index.test.ts"),
116
+ content
117
+ )
118
+ }
119
+
120
+ export function writeLicenseFile(root) {
121
+ const currentYear = new Date().getFullYear()
122
+
123
+ const content = `MIT License
124
+
125
+ Copyright (c) ${currentYear} Marcuth
126
+
127
+ Permission is hereby granted, free of charge, to any person obtaining a copy
128
+ of this software and associated documentation files (the "Software"), to deal
129
+ in the Software without restriction, including without limitation the rights
130
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
131
+ copies of the Software, and to permit persons to whom the Software is
132
+ furnished to do so, subject to the following conditions:
133
+
134
+ The above copyright notice and this permission notice shall be included in all
135
+ copies or substantial portions of the Software.
136
+
137
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
138
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
139
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
140
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
141
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
142
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
143
+ SOFTWARE.`
144
+
145
+ fs.writeFileSync(
146
+ path.join(root, "LICENSE"),
147
+ content
148
+ )
149
+ }
150
+
151
+ export function writeGitignoreFile(root) {
152
+ const content = `# Created by https://www.toptal.com/developers/gitignore/api/node
153
+ # Edit at https://www.toptal.com/developers/gitignore?templates=node
154
+
155
+ ### Node ###
156
+ # Logs
157
+ dist/
158
+ logs
159
+ *.log
160
+ npm-debug.log*
161
+ yarn-debug.log*
162
+ yarn-error.log*
163
+ lerna-debug.log*
164
+ .pnpm-debug.log*
165
+
166
+ # Diagnostic reports (https://nodejs.org/api/report.html)
167
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
168
+
169
+ # Runtime data
170
+ pids
171
+ *.pid
172
+ *.seed
173
+ *.pid.lock
174
+
175
+ # Directory for instrumented libs generated by jscoverage/JSCover
176
+ lib-cov
177
+
178
+ # Coverage directory used by tools like istanbul
179
+ coverage
180
+ *.lcov
181
+
182
+ # nyc test coverage
183
+ .nyc_output
184
+
185
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
186
+ .grunt
187
+
188
+ # Bower dependency directory (https://bower.io/)
189
+ bower_components
190
+
191
+ # node-waf configuration
192
+ .lock-wscript
193
+
194
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
195
+ build/Release
196
+
197
+ # Dependency directories
198
+ node_modules/
199
+ jspm_packages/
200
+
201
+ # Snowpack dependency directory (https://snowpack.dev/)
202
+ web_modules/
203
+
204
+ # TypeScript cache
205
+ *.tsbuildinfo
206
+
207
+ # Optional npm cache directory
208
+ .npm
209
+
210
+ # Optional eslint cache
211
+ .eslintcache
212
+
213
+ # Optional stylelint cache
214
+ .stylelintcache
215
+
216
+ # Microbundle cache
217
+ .rpt2_cache/
218
+ .rts2_cache_cjs/
219
+ .rts2_cache_es/
220
+ .rts2_cache_umd/
221
+
222
+ # Optional REPL history
223
+ .node_repl_history
224
+
225
+ # Output of 'npm pack'
226
+ *.tgz
227
+
228
+ # Yarn Integrity file
229
+ .yarn-integrity
230
+
231
+ # dotenv environment variable files
232
+ .env
233
+ .env.development.local
234
+ .env.test.local
235
+ .env.production.local
236
+ .env.local
237
+
238
+ # parcel-bundler cache (https://parceljs.org/)
239
+ .cache
240
+ .parcel-cache
241
+
242
+ # Next.js build output
243
+ .next
244
+ out
245
+
246
+ # Nuxt.js build / generate output
247
+ .nuxt
248
+ dist
249
+
250
+ # Gatsby files
251
+ .cache/
252
+ # Comment in the public line in if your project uses Gatsby and not Next.js
253
+ # https://nextjs.org/blog/next-9-1#public-directory-support
254
+ # public
255
+
256
+ # vuepress build output
257
+ .vuepress/dist
258
+
259
+ # vuepress v2.x temp and cache directory
260
+ .temp
261
+
262
+ # Docusaurus cache and generated files
263
+ .docusaurus
264
+
265
+ # Serverless directories
266
+ .serverless/
267
+
268
+ # FuseBox cache
269
+ .fusebox/
270
+
271
+ # DynamoDB Local files
272
+ .dynamodb/
273
+
274
+ # TernJS port file
275
+ .tern-port
276
+
277
+ # Stores VSCode versions used for testing VSCode extensions
278
+ .vscode-test
279
+
280
+ # yarn v2
281
+ .yarn/cache
282
+ .yarn/unplugged
283
+ .yarn/build-state.yml
284
+ .yarn/install-state.gz
285
+ .pnp.*
286
+
287
+ ### Node Patch ###
288
+ # Serverless Webpack directories
289
+ .webpack/
290
+
291
+ # Optional stylelint cache
292
+
293
+ # SvelteKit build / generate output
294
+ .svelte-kit
295
+
296
+ # End of https://www.toptal.com/developers/gitignore/api/node`
297
+
298
+ fs.writeFileSync(
299
+ path.join(root, ".gitignore"),
300
+ content
301
+ )
302
+ }
303
+
304
+ export function writeGitAttributes(root) {
305
+ const content = `*.js linguist-generated=true
306
+ *.d.ts linguist-generated=true`
307
+
308
+ fs.writeFileSync(
309
+ path.join(root, ".gitattributes"),
310
+ content
311
+ )
312
+ }
313
+
314
+ export function createNpmIgnore(root) {
315
+ const content = `src/
316
+ tsconfig.json`
317
+
318
+ fs.writeFileSync(
319
+ path.join(root, ".npmignore"),
320
+ content
321
+ )
322
+ }
323
+
324
+ export function createReadme(root, packageName) {
325
+ const content = `# ${packageName}`
326
+
327
+ fs.writeFileSync(
328
+ path.join(root, "README.md"),
329
+ content
330
+ )
331
+ }
332
+
333
+ export function createEsLintRcConfig(root) {
334
+ const content = {
335
+ "extends": [
336
+ "plugin:prettier/recommended"
337
+ ],
338
+ "plugins": [
339
+ "prettier",
340
+ "unused-imports"
341
+ ],
342
+ "rules": {
343
+ "prettier/prettier": "error",
344
+ "no-unused-vars": "off",
345
+ "unused-imports/no-unused-imports": "error",
346
+ "unused-imports/no-unused-vars": [
347
+ "warn",
348
+ { "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" }
349
+ ]
350
+ }
351
+ }
352
+
353
+ fs.writeFileSync(
354
+ path.join(root, ".eslintrc.json"),
355
+ JSON.stringify(content, null, 4)
356
+ )
357
+ }
358
+
359
+ export function createPrettierConfig(root) {
360
+ const content = `module.exports = {
361
+ "semi": false,
362
+ "singleQuote": false,
363
+ "tabWidth": 4,
364
+ "useTabs": false,
365
+ "importTypeOrder": ["NPMPackages", "localImports"],
366
+ "newlineBetweenTypes": true,
367
+ "sortingMethod": "lineLength",
368
+ "plugins": ["./node_modules/prettier-plugin-sort-imports/dist/index.js"],
369
+ "endOfLine": "auto",
370
+ "printWidth": 120
371
+ }`
372
+
373
+ fs.writeFileSync(
374
+ path.join(root, ".prettierrc.js"),
375
+ content
376
+ )
377
+ }