create-planke 0.0.1
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/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/index.mjs +303 -0
- package/package.json +61 -0
- package/template/package.json +15 -0
- package/template/tsconfig.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Espen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# planke
|
|
2
|
+
|
|
3
|
+
**The Unified Toolchain Starter for Node.js**
|
|
4
|
+
|
|
5
|
+
Creates a new Node.js TypeScript project using the same opinionated toolchain as [Vite+](https://github.com/voidzero-dev/vite-plus), but for non-web projects.
|
|
6
|
+
|
|
7
|
+
## Create a new project with planke
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm create planke@latest
|
|
11
|
+
npm create planke@latest
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## What you get
|
|
15
|
+
|
|
16
|
+
The project follows most of the same toolchain as Vite+.
|
|
17
|
+
|
|
18
|
+
| Tool | Role |
|
|
19
|
+
| -------------------------------------------------- | ------------------ |
|
|
20
|
+
| [Vitest](https://vitest.dev) | Testing |
|
|
21
|
+
| [Oxlint](https://oxc.rs/docs/guide/usage/linter) | Linting |
|
|
22
|
+
| [Oxfmt](https://oxc.rs/docs/guide/usage/formatter) | Formatting |
|
|
23
|
+
| [tsdown](https://tsdown.dev) | Build & bundle |
|
|
24
|
+
| [tsx](https://tsx.is) | Dev-mode execution |
|
|
25
|
+
|
|
26
|
+
## Backend framework
|
|
27
|
+
|
|
28
|
+
You can also choose one of the following backend frameworks:
|
|
29
|
+
|
|
30
|
+
- **None** — where you don't need a API framework, or you want to pick your own.
|
|
31
|
+
- **Hono** — lightweight, modern API framework
|
|
32
|
+
- **Fastify** — fast and low overhead
|
|
33
|
+
- **Express** — familiar and widely supported
|
|
34
|
+
|
|
35
|
+
## Scripts
|
|
36
|
+
|
|
37
|
+
Every generated project includes:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pnpm dev # Run with tsx (no build step)
|
|
41
|
+
pnpm build # Bundle with tsdown
|
|
42
|
+
pnpm test # Run Vitest
|
|
43
|
+
pnpm check # Lint + format check + type check
|
|
44
|
+
pnpm fmt # Format
|
|
45
|
+
pnpm fmt:check # Check formatting without writing
|
|
46
|
+
pnpm lint # Lint
|
|
47
|
+
pnpm lint:fix # Lint with auto-fix
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The `pnpm` commands are just examples, you can also use `npm` or `yarn` or `bun` (depending on your package manager).
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
|
55
|
+
|
|
56
|
+
## Author
|
|
57
|
+
|
|
58
|
+
- [Espen Steen](https://github.com/ehs5)
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import spawn from "cross-spawn";
|
|
6
|
+
import mri from "mri";
|
|
7
|
+
import * as p from "@clack/prompts";
|
|
8
|
+
import pc from "picocolors";
|
|
9
|
+
//#region src/frameworks.ts
|
|
10
|
+
const FRAMEWORKS = [
|
|
11
|
+
{
|
|
12
|
+
value: "none",
|
|
13
|
+
label: "None"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
value: "hono",
|
|
17
|
+
label: "Hono",
|
|
18
|
+
hint: "recommended"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
value: "fastify",
|
|
22
|
+
label: "Fastify"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
value: "express",
|
|
26
|
+
label: "Express"
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
const FRAMEWORK_DEPS = {
|
|
30
|
+
none: {
|
|
31
|
+
deps: [],
|
|
32
|
+
devDeps: []
|
|
33
|
+
},
|
|
34
|
+
hono: {
|
|
35
|
+
deps: ["hono", "@hono/node-server"],
|
|
36
|
+
devDeps: []
|
|
37
|
+
},
|
|
38
|
+
fastify: {
|
|
39
|
+
deps: ["fastify"],
|
|
40
|
+
devDeps: []
|
|
41
|
+
},
|
|
42
|
+
express: {
|
|
43
|
+
deps: ["express"],
|
|
44
|
+
devDeps: ["@types/express"]
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const FRAMEWORK_INDEX = {
|
|
48
|
+
none: `console.log('Hello from planke!')\n`,
|
|
49
|
+
hono: `import { Hono } from 'hono'
|
|
50
|
+
import { serve } from '@hono/node-server'
|
|
51
|
+
|
|
52
|
+
const app = new Hono()
|
|
53
|
+
|
|
54
|
+
app.get('/', (c) => c.text('Hello World'))
|
|
55
|
+
|
|
56
|
+
serve(app, (info) => {
|
|
57
|
+
console.log(\`Server running on http://localhost:\${info.port}\`)
|
|
58
|
+
})
|
|
59
|
+
`,
|
|
60
|
+
fastify: `import Fastify from 'fastify'
|
|
61
|
+
|
|
62
|
+
const fastify = Fastify({ logger: true })
|
|
63
|
+
|
|
64
|
+
fastify.get('/', async () => ({ hello: 'world' }))
|
|
65
|
+
|
|
66
|
+
fastify.listen({ port: 3000 })
|
|
67
|
+
`,
|
|
68
|
+
express: `import express from 'express'
|
|
69
|
+
|
|
70
|
+
const app = express()
|
|
71
|
+
|
|
72
|
+
app.get('/', (req, res) => {
|
|
73
|
+
res.send('Hello World')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
app.listen(3000, () => {
|
|
77
|
+
console.log('Server running on http://localhost:3000')
|
|
78
|
+
})
|
|
79
|
+
`
|
|
80
|
+
};
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/index.ts
|
|
83
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
84
|
+
/** Creates a colored gradient text effect */
|
|
85
|
+
function gradient(text, stops, whiteRange) {
|
|
86
|
+
const chars = [...text];
|
|
87
|
+
return chars.map((char, i) => {
|
|
88
|
+
if (whiteRange && i >= whiteRange[0] && i < whiteRange[1]) return `\x1b[38;2;255;255;255m${char}`;
|
|
89
|
+
const t = chars.length === 1 ? 0 : i / (chars.length - 1);
|
|
90
|
+
const seg = Math.min(Math.floor(t * (stops.length - 1)), stops.length - 2);
|
|
91
|
+
const segT = t * (stops.length - 1) - seg;
|
|
92
|
+
const [r1, g1, b1] = stops[seg];
|
|
93
|
+
const [r2, g2, b2] = stops[seg + 1];
|
|
94
|
+
return `\x1b[38;2;${Math.round(r1 + (r2 - r1) * segT)};${Math.round(g1 + (g2 - g1) * segT)};${Math.round(b1 + (b2 - b1) * segT)}m${char}`;
|
|
95
|
+
}).join("") + "\x1B[0m";
|
|
96
|
+
}
|
|
97
|
+
/** Detects the package manager used to invoke the CLI via npm_config_user_agent. */
|
|
98
|
+
function detectPkgManager() {
|
|
99
|
+
const ua = process.env.npm_config_user_agent ?? "";
|
|
100
|
+
if (ua.startsWith("pnpm")) return "pnpm";
|
|
101
|
+
if (ua.startsWith("bun")) return "bun";
|
|
102
|
+
if (ua.startsWith("yarn")) return "yarn";
|
|
103
|
+
return "npm";
|
|
104
|
+
}
|
|
105
|
+
/** Builds the install/add command args for the given package manager. */
|
|
106
|
+
function addArgs(pkgManager, packages, dev) {
|
|
107
|
+
const cmd = pkgManager === "npm" ? "install" : "add";
|
|
108
|
+
return dev ? [
|
|
109
|
+
cmd,
|
|
110
|
+
{
|
|
111
|
+
npm: "--save-dev",
|
|
112
|
+
pnpm: "-D",
|
|
113
|
+
yarn: "--dev",
|
|
114
|
+
bun: "-d"
|
|
115
|
+
}[pkgManager] ?? "--save-dev",
|
|
116
|
+
...packages
|
|
117
|
+
] : [cmd, ...packages];
|
|
118
|
+
}
|
|
119
|
+
/** Runs a command synchronously, exiting the process if it fails. */
|
|
120
|
+
function run(cmd, args, opts) {
|
|
121
|
+
const result = spawn.sync(cmd, args, {
|
|
122
|
+
stdio: "inherit",
|
|
123
|
+
...opts
|
|
124
|
+
});
|
|
125
|
+
if (result.status != null && result.status !== 0) process.exit(result.status);
|
|
126
|
+
if (result.error) throw result.error;
|
|
127
|
+
}
|
|
128
|
+
/** Recursively copies a directory, renaming _gitignore to .gitignore. */
|
|
129
|
+
function copyDir(src, dest) {
|
|
130
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
131
|
+
for (const entry of fs.readdirSync(src)) {
|
|
132
|
+
const srcPath = path.join(src, entry);
|
|
133
|
+
const destPath = path.join(dest, entry === "_gitignore" ? ".gitignore" : entry);
|
|
134
|
+
if (fs.statSync(srcPath).isDirectory()) copyDir(srcPath, destPath);
|
|
135
|
+
else fs.copyFileSync(srcPath, destPath);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/** Returns true if a directory doesn't exist or contains only a .git folder. */
|
|
139
|
+
function isEmpty(dir) {
|
|
140
|
+
if (!fs.existsSync(dir)) return true;
|
|
141
|
+
const files = fs.readdirSync(dir);
|
|
142
|
+
return files.length === 0 || files.length === 1 && files[0] === ".git";
|
|
143
|
+
}
|
|
144
|
+
/** Prompts for a project name, or reads it from the first CLI argument. */
|
|
145
|
+
async function promptProjectName(argv) {
|
|
146
|
+
const fromArg = argv._[0] ?? "";
|
|
147
|
+
if (fromArg) return fromArg;
|
|
148
|
+
const answer = await p.text({
|
|
149
|
+
message: "Project name:",
|
|
150
|
+
placeholder: "planke-project",
|
|
151
|
+
defaultValue: "planke-project"
|
|
152
|
+
});
|
|
153
|
+
if (p.isCancel(answer)) {
|
|
154
|
+
p.cancel("Cancelled");
|
|
155
|
+
process.exit(0);
|
|
156
|
+
}
|
|
157
|
+
return answer || "planke-project";
|
|
158
|
+
}
|
|
159
|
+
/** Prompts for a backend framework, or reads it from the --template flag. */
|
|
160
|
+
async function promptFramework(argv) {
|
|
161
|
+
const templateArg = argv.template;
|
|
162
|
+
if (templateArg && FRAMEWORK_DEPS[templateArg]) return templateArg;
|
|
163
|
+
const answer = await p.select({
|
|
164
|
+
message: "Backend framework:",
|
|
165
|
+
options: FRAMEWORKS,
|
|
166
|
+
initialValue: "none"
|
|
167
|
+
});
|
|
168
|
+
if (p.isCancel(answer)) {
|
|
169
|
+
p.cancel("Cancelled");
|
|
170
|
+
process.exit(0);
|
|
171
|
+
}
|
|
172
|
+
return answer;
|
|
173
|
+
}
|
|
174
|
+
/** Asks the user to confirm before wiping a non-empty target directory. */
|
|
175
|
+
async function confirmOverwrite(projectName, targetDir) {
|
|
176
|
+
if (isEmpty(targetDir)) return;
|
|
177
|
+
const overwrite = await p.confirm({ message: `${pc.yellow(projectName)} is not empty. Remove existing files and continue?` });
|
|
178
|
+
if (p.isCancel(overwrite) || !overwrite) {
|
|
179
|
+
p.cancel("Cancelled");
|
|
180
|
+
process.exit(0);
|
|
181
|
+
}
|
|
182
|
+
fs.rmSync(targetDir, {
|
|
183
|
+
recursive: true,
|
|
184
|
+
force: true
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/** Copies the base template, sets the package name, and writes the framework starter code. */
|
|
188
|
+
function scaffoldFiles(projectName, framework, targetDir) {
|
|
189
|
+
copyDir(path.join(__dirname, "..", "template"), targetDir);
|
|
190
|
+
const pkgJsonPath = path.join(targetDir, "package.json");
|
|
191
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
192
|
+
pkg.name = projectName;
|
|
193
|
+
fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
194
|
+
fs.mkdirSync(path.join(targetDir, "src"), { recursive: true });
|
|
195
|
+
fs.writeFileSync(path.join(targetDir, "src", "index.ts"), FRAMEWORK_INDEX[framework]);
|
|
196
|
+
}
|
|
197
|
+
/** Installs shared dev dependencies and any framework-specific packages. */
|
|
198
|
+
function installDependencies(pkgManager, framework, targetDir) {
|
|
199
|
+
p.log.step(`Installing dependencies with ${pkgManager}...`);
|
|
200
|
+
run(pkgManager, addArgs(pkgManager, [
|
|
201
|
+
"@types/node",
|
|
202
|
+
"oxfmt",
|
|
203
|
+
"oxlint",
|
|
204
|
+
"tsdown",
|
|
205
|
+
"tsx",
|
|
206
|
+
"typescript",
|
|
207
|
+
"vitest"
|
|
208
|
+
], true), { cwd: targetDir });
|
|
209
|
+
/** Install framework dependencies */
|
|
210
|
+
if (framework !== "none") {
|
|
211
|
+
p.log.step(`Installing ${framework}...`);
|
|
212
|
+
const frameworkDeps = FRAMEWORK_DEPS[framework];
|
|
213
|
+
if (frameworkDeps.deps.length > 0) run(pkgManager, addArgs(pkgManager, frameworkDeps.deps, false), { cwd: targetDir });
|
|
214
|
+
if (frameworkDeps.devDeps.length > 0) run(pkgManager, addArgs(pkgManager, frameworkDeps.devDeps, true), { cwd: targetDir });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/** Prints the gradient outro with next steps. */
|
|
218
|
+
function showOutro(projectName, framework, pkgManager) {
|
|
219
|
+
const frameworkLabel = FRAMEWORKS.find((f) => f.value === framework)?.label ?? framework;
|
|
220
|
+
const outroStops = [[
|
|
221
|
+
168,
|
|
222
|
+
85,
|
|
223
|
+
247
|
|
224
|
+
], [
|
|
225
|
+
99,
|
|
226
|
+
102,
|
|
227
|
+
241
|
|
228
|
+
]];
|
|
229
|
+
const outroText = frameworkLabel !== "None" ? `Created ${projectName} with ${frameworkLabel}` : `Created ${projectName}`;
|
|
230
|
+
const nameStart = 8;
|
|
231
|
+
const outro = gradient(outroText, outroStops, [nameStart, nameStart + projectName.length]);
|
|
232
|
+
const devCmd = pkgManager === "npm" ? "npm run dev" : `${pkgManager} dev`;
|
|
233
|
+
p.outro(`${outro}\n\n ${pc.dim("Now run:")}\n cd ${projectName}\n ${devCmd}`);
|
|
234
|
+
}
|
|
235
|
+
async function main() {
|
|
236
|
+
const argv = mri(process.argv.slice(2), {
|
|
237
|
+
string: ["template"],
|
|
238
|
+
alias: { t: "template" }
|
|
239
|
+
});
|
|
240
|
+
p.intro(pc.bold(gradient("planke - The Unified Toolchain Starter for Node.js", [
|
|
241
|
+
[
|
|
242
|
+
255,
|
|
243
|
+
255,
|
|
244
|
+
255
|
|
245
|
+
],
|
|
246
|
+
[
|
|
247
|
+
168,
|
|
248
|
+
85,
|
|
249
|
+
247
|
|
250
|
+
],
|
|
251
|
+
[
|
|
252
|
+
99,
|
|
253
|
+
102,
|
|
254
|
+
241
|
|
255
|
+
]
|
|
256
|
+
], [0, 6])));
|
|
257
|
+
const projectName = await promptProjectName(argv);
|
|
258
|
+
const framework = await promptFramework(argv);
|
|
259
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
260
|
+
const pkgManager = detectPkgManager();
|
|
261
|
+
await confirmOverwrite(projectName, targetDir);
|
|
262
|
+
scaffoldFiles(projectName, framework, targetDir);
|
|
263
|
+
run("git", [
|
|
264
|
+
"init",
|
|
265
|
+
"-b",
|
|
266
|
+
"main"
|
|
267
|
+
], {
|
|
268
|
+
cwd: targetDir,
|
|
269
|
+
stdio: "ignore"
|
|
270
|
+
});
|
|
271
|
+
p.log.step("Initializing git repository");
|
|
272
|
+
installDependencies(pkgManager, framework, targetDir);
|
|
273
|
+
p.log.step("Formatting code");
|
|
274
|
+
run(pkgManager, [
|
|
275
|
+
"exec",
|
|
276
|
+
"oxlint",
|
|
277
|
+
"--",
|
|
278
|
+
"--init"
|
|
279
|
+
], {
|
|
280
|
+
cwd: targetDir,
|
|
281
|
+
stdio: "ignore"
|
|
282
|
+
});
|
|
283
|
+
run(pkgManager, [
|
|
284
|
+
"exec",
|
|
285
|
+
"oxfmt",
|
|
286
|
+
"--",
|
|
287
|
+
"--init"
|
|
288
|
+
], {
|
|
289
|
+
cwd: targetDir,
|
|
290
|
+
stdio: "ignore"
|
|
291
|
+
});
|
|
292
|
+
run(pkgManager, ["exec", "oxfmt"], {
|
|
293
|
+
cwd: targetDir,
|
|
294
|
+
stdio: "ignore"
|
|
295
|
+
});
|
|
296
|
+
showOutro(projectName, framework, pkgManager);
|
|
297
|
+
}
|
|
298
|
+
main().catch((err) => {
|
|
299
|
+
console.error(err);
|
|
300
|
+
process.exit(1);
|
|
301
|
+
});
|
|
302
|
+
//#endregion
|
|
303
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-planke",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "The Unified Toolchain Starter for Node.js",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"backend",
|
|
7
|
+
"create-planke",
|
|
8
|
+
"express",
|
|
9
|
+
"fastify",
|
|
10
|
+
"framework",
|
|
11
|
+
"hono",
|
|
12
|
+
"oxfmt",
|
|
13
|
+
"oxlint",
|
|
14
|
+
"planke",
|
|
15
|
+
"scaffolder",
|
|
16
|
+
"toolchain",
|
|
17
|
+
"tsdown",
|
|
18
|
+
"tsx",
|
|
19
|
+
"typescript",
|
|
20
|
+
"vite+",
|
|
21
|
+
"vite-plus",
|
|
22
|
+
"viteplus",
|
|
23
|
+
"vitest"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"author": "Espen Steen",
|
|
27
|
+
"bin": {
|
|
28
|
+
"create-planke": "./dist/index.mjs"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"template"
|
|
33
|
+
],
|
|
34
|
+
"type": "module",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@clack/prompts": "^1.1.0",
|
|
37
|
+
"cross-spawn": "^7.0.6",
|
|
38
|
+
"mri": "^1.2.0",
|
|
39
|
+
"picocolors": "^1.1.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/cross-spawn": "^6.0.6",
|
|
43
|
+
"@types/node": "^25.5.0",
|
|
44
|
+
"oxfmt": "^0.43.0",
|
|
45
|
+
"oxlint": "^1.58.0",
|
|
46
|
+
"tsdown": "^0.21.7",
|
|
47
|
+
"tsx": "^4.21.0",
|
|
48
|
+
"typescript": "^6.0.2",
|
|
49
|
+
"vitest": "^4.1.2"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"test": "vitest",
|
|
53
|
+
"lint": "oxlint",
|
|
54
|
+
"lint:fix": "oxlint --fix",
|
|
55
|
+
"fmt": "oxfmt",
|
|
56
|
+
"fmt:check": "oxfmt --check",
|
|
57
|
+
"check": "oxlint && oxfmt --check && tsc --noEmit",
|
|
58
|
+
"dev": "tsx src/index.ts",
|
|
59
|
+
"build": "tsdown src/index.ts"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "planke-project",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "tsx src/index.ts",
|
|
7
|
+
"build": "tsdown src/index.ts",
|
|
8
|
+
"test": "vitest",
|
|
9
|
+
"lint": "oxlint",
|
|
10
|
+
"lint:fix": "oxlint --fix",
|
|
11
|
+
"fmt": "oxfmt",
|
|
12
|
+
"fmt:check": "oxfmt --check",
|
|
13
|
+
"check": "oxlint && oxfmt --check && tsc --noEmit"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"verbatimModuleSyntax": true,
|
|
9
|
+
"noUnusedLocals": true,
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
"outDir": "./dist"
|
|
12
|
+
},
|
|
13
|
+
"exclude": ["node_modules"]
|
|
14
|
+
}
|