luvabase 0.0.4

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.
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "snake",
3
+ "version": "1.0.0",
4
+ "scripts": {
5
+ "clean": "rm -rf dist && rm -f snake.luva",
6
+ "dist": "npm run clean && mkdir dist && cp -r luva.jsonc icon.png public dist/",
7
+ "build:luva": "npm run dist && cd dist && zip -r ../snake.luva .",
8
+ "dev": "vite dev"
9
+ },
10
+ "devDependencies": {
11
+ "vite": "^6.3.5"
12
+ }
13
+ }
@@ -0,0 +1,602 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
7
+ <title>Snake Game</title>
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ body {
16
+ background: linear-gradient(135deg, #f7f3ea 0%, #f0ead6 100%);
17
+ display: flex;
18
+ justify-content: center;
19
+ align-items: center;
20
+ min-height: 100vh;
21
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
22
+ overflow: hidden;
23
+ touch-action: none;
24
+ -webkit-touch-callout: none;
25
+ -webkit-user-select: none;
26
+ user-select: none;
27
+ -webkit-tap-highlight-color: transparent;
28
+ padding: 20px;
29
+ box-sizing: border-box;
30
+ }
31
+
32
+ canvas {
33
+ border: none;
34
+ background: #ffffff;
35
+ border-radius: 20px;
36
+ box-shadow:
37
+ 0 10px 30px rgba(0, 0, 0, 0.1),
38
+ 0 1px 8px rgba(0, 0, 0, 0.05),
39
+ inset 0 1px 0 rgba(255, 255, 255, 0.8);
40
+ max-width: 100%;
41
+ max-height: 100%;
42
+ }
43
+
44
+ .game-info {
45
+ position: absolute;
46
+ top: 30px;
47
+ left: 30px;
48
+ color: #6b5b47;
49
+ font-size: 20px;
50
+ z-index: 10;
51
+ font-weight: 600;
52
+ background: rgba(255, 255, 255, 0.9);
53
+ padding: 12px 16px;
54
+ border-radius: 12px;
55
+ backdrop-filter: blur(10px);
56
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
57
+ }
58
+
59
+ .game-over {
60
+ position: absolute;
61
+ top: 50%;
62
+ left: 50%;
63
+ transform: translate(-50%, -50%);
64
+ color: #6b5b47;
65
+ text-align: center;
66
+ z-index: 20;
67
+ display: none;
68
+ background: rgba(255, 255, 255, 0.95);
69
+ padding: 48px 40px;
70
+ border-radius: 24px;
71
+ backdrop-filter: blur(20px);
72
+ box-shadow:
73
+ 0 20px 40px rgba(0, 0, 0, 0.15),
74
+ 0 8px 16px rgba(0, 0, 0, 0.1);
75
+ border: 1px solid rgba(255, 255, 255, 0.8);
76
+ }
77
+
78
+ .game-over h2 {
79
+ font-size: 32px;
80
+ margin-bottom: 20px;
81
+ color: #e74c3c;
82
+ font-weight: 700;
83
+ letter-spacing: -0.5px;
84
+ }
85
+
86
+ .game-over p {
87
+ font-size: 18px;
88
+ margin-bottom: 12px;
89
+ font-weight: 500;
90
+ line-height: 1.4;
91
+ }
92
+
93
+ .controls {
94
+ position: absolute;
95
+ bottom: 30px;
96
+ left: 30px;
97
+ color: #8b7d63;
98
+ font-size: 14px;
99
+ font-weight: 500;
100
+ background: rgba(255, 255, 255, 0.8);
101
+ padding: 10px 14px;
102
+ border-radius: 10px;
103
+ backdrop-filter: blur(10px);
104
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
105
+ }
106
+
107
+ .desktop-only {
108
+ display: block;
109
+ }
110
+
111
+ .mobile-only {
112
+ display: none;
113
+ }
114
+
115
+ @media (max-width: 768px) {
116
+ .game-info {
117
+ top: 20px;
118
+ left: 20px;
119
+ right: 20px;
120
+ font-size: 18px;
121
+ padding: 10px 14px;
122
+ }
123
+
124
+ .controls {
125
+ bottom: 20px;
126
+ left: 20px;
127
+ right: 20px;
128
+ text-align: center;
129
+ font-size: 13px;
130
+ padding: 8px 12px;
131
+ }
132
+
133
+ .game-over {
134
+ left: 20px;
135
+ right: 20px;
136
+ transform: translateY(-50%);
137
+ padding: 32px 24px;
138
+ margin: 0 auto;
139
+ max-width: 320px;
140
+ }
141
+
142
+ .desktop-only {
143
+ display: none;
144
+ }
145
+ .mobile-only {
146
+ display: block;
147
+ }
148
+ }
149
+ </style>
150
+ </head>
151
+
152
+ <body>
153
+ <div class="game-info">
154
+ <div>Score: <span id="score">0</span></div>
155
+ <div>High Score: <span id="highScore">0</span></div>
156
+ </div>
157
+
158
+ <div class="game-over" id="gameOver">
159
+ <h2>Game Over!</h2>
160
+ <p>Final Score: <span id="finalScore">0</span></p>
161
+ <p>Tap to restart</p>
162
+ </div>
163
+
164
+ <div class="controls">
165
+ <p class="desktop-only">Use ARROW KEYS or WASD to move</p>
166
+ <p class="mobile-only">Swipe to move</p>
167
+ </div>
168
+
169
+ <canvas id="gameCanvas" tabindex="0"></canvas>
170
+
171
+ <script>
172
+ class SnakeGame {
173
+ constructor() {
174
+ this.canvas = document.getElementById('gameCanvas');
175
+ this.ctx = this.canvas.getContext('2d');
176
+ this.scoreElement = document.getElementById('score');
177
+ this.highScoreElement = document.getElementById('highScore');
178
+ this.gameOverElement = document.getElementById('gameOver');
179
+ this.finalScoreElement = document.getElementById('finalScore');
180
+
181
+ this.gridSize = 32;
182
+ this.tileCount = 0;
183
+
184
+ this.snake = [];
185
+ this.food = {};
186
+ this.dx = 0;
187
+ this.dy = 0;
188
+ this.score = 0;
189
+ this.highScore = localStorage.getItem('snakeHighScore') || 0;
190
+ this.gameRunning = false;
191
+ this.gameSpeed = 150;
192
+ this.lastFrameTime = 0;
193
+ this.inputBuffer = [];
194
+ this.sounds = {
195
+ eat: this.createSound(800, 0.1, 'square'),
196
+ gameOver: this.createSound(200, 0.5, 'sawtooth')
197
+ };
198
+
199
+ this.setupCanvas();
200
+ this.canvas.focus();
201
+ this.initGame();
202
+ this.bindEvents();
203
+ this.gameLoop();
204
+ }
205
+
206
+ setupCanvas() {
207
+ // Better mobile spacing and responsive design
208
+ const isMobile = window.innerWidth <= 768;
209
+ const padding = isMobile ? 40 : 80;
210
+ const maxWidth = window.innerWidth - padding;
211
+ const maxHeight = window.innerHeight - padding - (isMobile ? 120 : 160); // Account for UI elements
212
+
213
+ // Make grid size proportional to canvas size for better gameplay
214
+ const minDimension = Math.min(maxWidth, maxHeight);
215
+ this.tileCount = Math.max(12, Math.floor(minDimension / this.gridSize));
216
+
217
+ this.canvas.width = this.tileCount * this.gridSize;
218
+ this.canvas.height = this.tileCount * this.gridSize;
219
+ }
220
+
221
+ initGame() {
222
+ const centerY = Math.floor(this.tileCount / 2);
223
+ this.snake = [
224
+ { x: 2, y: centerY },
225
+ { x: 1, y: centerY },
226
+ { x: 0, y: centerY }
227
+ ];
228
+ this.dx = 1;
229
+ this.dy = 0;
230
+ this.score = 0;
231
+ this.gameRunning = true;
232
+ this.gameSpeed = 150;
233
+ this.lastFrameTime = 0;
234
+ this.inputBuffer = [];
235
+ this.highScoreElement.textContent = this.highScore;
236
+ this.scoreElement.textContent = this.score;
237
+ this.gameOverElement.style.display = 'none';
238
+ this.generateFood();
239
+ }
240
+
241
+ generateFood() {
242
+ const availablePositions = [];
243
+
244
+ // Find all positions not occupied by snake
245
+ for (let x = 0; x < this.tileCount; x++) {
246
+ for (let y = 0; y < this.tileCount; y++) {
247
+ const isOccupied = this.snake.some(segment => segment.x === x && segment.y === y);
248
+ if (!isOccupied) {
249
+ availablePositions.push({ x, y });
250
+ }
251
+ }
252
+ }
253
+
254
+ // If no available positions (game won), place food anywhere
255
+ if (availablePositions.length === 0) {
256
+ this.food = {
257
+ x: Math.floor(Math.random() * this.tileCount),
258
+ y: Math.floor(Math.random() * this.tileCount)
259
+ };
260
+ } else {
261
+ const randomIndex = Math.floor(Math.random() * availablePositions.length);
262
+ this.food = availablePositions[randomIndex];
263
+ }
264
+ }
265
+
266
+ bindEvents() {
267
+ document.addEventListener('keydown', (e) => {
268
+ if (!this.gameRunning) return;
269
+
270
+ const keyMap = {
271
+ 'ArrowUp': { dx: 0, dy: -1 },
272
+ 'ArrowDown': { dx: 0, dy: 1 },
273
+ 'ArrowLeft': { dx: -1, dy: 0 },
274
+ 'ArrowRight': { dx: 1, dy: 0 },
275
+ 'KeyW': { dx: 0, dy: -1 },
276
+ 'KeyS': { dx: 0, dy: 1 },
277
+ 'KeyA': { dx: -1, dy: 0 },
278
+ 'KeyD': { dx: 1, dy: 0 }
279
+ };
280
+
281
+ const direction = keyMap[e.code];
282
+ if (direction) {
283
+ this.setDirection(direction.dx, direction.dy);
284
+ }
285
+ });
286
+
287
+ // Touch tap to restart when game over
288
+ this.gameOverElement.addEventListener('touchend', (e) => {
289
+ e.preventDefault();
290
+ if (!this.gameRunning) {
291
+ this.initGame();
292
+ }
293
+ });
294
+
295
+ this.gameOverElement.addEventListener('click', (e) => {
296
+ if (!this.gameRunning) {
297
+ this.initGame();
298
+ }
299
+ });
300
+
301
+ window.addEventListener('resize', () => {
302
+ this.setupCanvas();
303
+ });
304
+
305
+ this.canvas.addEventListener('click', () => {
306
+ this.canvas.focus();
307
+ });
308
+
309
+ // Touch swipe controls
310
+ let touchStartX = 0;
311
+ let touchStartY = 0;
312
+ const minSwipeDistance = 30;
313
+
314
+ this.canvas.addEventListener('touchstart', (e) => {
315
+ e.preventDefault();
316
+ const touch = e.touches[0];
317
+ touchStartX = touch.clientX;
318
+ touchStartY = touch.clientY;
319
+ });
320
+
321
+ this.canvas.addEventListener('touchend', (e) => {
322
+ e.preventDefault();
323
+ if (!e.changedTouches) return;
324
+
325
+ const touch = e.changedTouches[0];
326
+ const touchEndX = touch.clientX;
327
+ const touchEndY = touch.clientY;
328
+
329
+ const deltaX = touchEndX - touchStartX;
330
+ const deltaY = touchEndY - touchStartY;
331
+
332
+ // Check if swipe distance is sufficient
333
+ if (Math.abs(deltaX) < minSwipeDistance && Math.abs(deltaY) < minSwipeDistance) {
334
+ return;
335
+ }
336
+
337
+ // Determine swipe direction
338
+ if (Math.abs(deltaX) > Math.abs(deltaY)) {
339
+ // Horizontal swipe
340
+ if (deltaX > 0) {
341
+ this.handleDirectionInput('right');
342
+ } else {
343
+ this.handleDirectionInput('left');
344
+ }
345
+ } else {
346
+ // Vertical swipe
347
+ if (deltaY > 0) {
348
+ this.handleDirectionInput('down');
349
+ } else {
350
+ this.handleDirectionInput('up');
351
+ }
352
+ }
353
+ });
354
+ }
355
+
356
+ handleDirectionInput(direction) {
357
+ if (!this.gameRunning) return;
358
+
359
+ const directionMap = {
360
+ 'up': { dx: 0, dy: -1 },
361
+ 'down': { dx: 0, dy: 1 },
362
+ 'left': { dx: -1, dy: 0 },
363
+ 'right': { dx: 1, dy: 0 }
364
+ };
365
+
366
+ const dir = directionMap[direction];
367
+ if (dir) {
368
+ this.setDirection(dir.dx, dir.dy);
369
+ }
370
+ }
371
+
372
+ setDirection(dx, dy) {
373
+ // Add to input buffer instead of setting directly
374
+ if (this.inputBuffer.length < 3) {
375
+ this.inputBuffer.push({ dx, dy });
376
+ }
377
+ }
378
+
379
+ processInputBuffer() {
380
+ if (this.inputBuffer.length === 0) return;
381
+
382
+ const nextInput = this.inputBuffer[0];
383
+
384
+ // Prevent reversing into self
385
+ if (this.snake.length > 1) {
386
+ if (nextInput.dx === -this.dx && nextInput.dy === -this.dy) {
387
+ this.inputBuffer.shift(); // Remove invalid input
388
+ return;
389
+ }
390
+ }
391
+
392
+ // Apply the direction change
393
+ this.dx = nextInput.dx;
394
+ this.dy = nextInput.dy;
395
+ this.inputBuffer.shift(); // Remove processed input
396
+ }
397
+
398
+ update() {
399
+ if (!this.gameRunning) return;
400
+
401
+ // Process buffered input
402
+ this.processInputBuffer();
403
+
404
+ // Don't update if snake isn't moving yet
405
+ if (this.dx === 0 && this.dy === 0) return;
406
+
407
+ let head = { x: this.snake[0].x + this.dx, y: this.snake[0].y + this.dy };
408
+
409
+ // Wrap around walls instead of collision
410
+ if (head.x < 0) {
411
+ head.x = this.tileCount - 1;
412
+ } else if (head.x >= this.tileCount) {
413
+ head.x = 0;
414
+ }
415
+
416
+ if (head.y < 0) {
417
+ head.y = this.tileCount - 1;
418
+ } else if (head.y >= this.tileCount) {
419
+ head.y = 0;
420
+ }
421
+
422
+ // Check self collision
423
+ for (let segment of this.snake) {
424
+ if (head.x === segment.x && head.y === segment.y) {
425
+ this.gameOver();
426
+ return;
427
+ }
428
+ }
429
+
430
+ this.snake.unshift(head);
431
+
432
+ // Check food collision
433
+ if (head.x === this.food.x && head.y === this.food.y) {
434
+ this.score += 10;
435
+ this.scoreElement.textContent = this.score;
436
+
437
+ // Play eat sound
438
+ this.playSound(this.sounds.eat);
439
+
440
+ // Increase speed slightly with each food eaten
441
+ this.gameSpeed = Math.max(80, this.gameSpeed - 3);
442
+
443
+ this.generateFood();
444
+ } else {
445
+ this.snake.pop();
446
+ }
447
+ }
448
+
449
+ draw() {
450
+ // Clear canvas with subtle gradient background
451
+ const gradient = this.ctx.createRadialGradient(
452
+ this.canvas.width / 2, this.canvas.height / 2, 0,
453
+ this.canvas.width / 2, this.canvas.height / 2, this.canvas.width / 2
454
+ );
455
+ gradient.addColorStop(0, '#f7f3ea');
456
+ gradient.addColorStop(1, '#f0ead6');
457
+ this.ctx.fillStyle = gradient;
458
+ this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
459
+
460
+ // Draw snake with clean, playful design
461
+ for (let i = 0; i < this.snake.length; i++) {
462
+ const segment = this.snake[i];
463
+ const x = segment.x * this.gridSize + 4;
464
+ const y = segment.y * this.gridSize + 4;
465
+ const size = this.gridSize - 8;
466
+ const radius = size / 2;
467
+
468
+ if (i === 0) {
469
+ // Snake head - simple rounded rectangle with eyes
470
+ this.ctx.fillStyle = '#7ba05b';
471
+ this.ctx.beginPath();
472
+ this.ctx.roundRect(x, y, size, size, radius * 0.6);
473
+ this.ctx.fill();
474
+
475
+ // Simple eyes
476
+ this.ctx.fillStyle = '#2d3436';
477
+ const eyeSize = Math.max(3, this.gridSize / 12);
478
+ const eyeOffset = radius * 0.4;
479
+
480
+ this.ctx.beginPath();
481
+ this.ctx.arc(x + radius - eyeOffset, y + radius - eyeOffset * 0.3, eyeSize, 0, 2 * Math.PI);
482
+ this.ctx.arc(x + radius + eyeOffset, y + radius - eyeOffset * 0.3, eyeSize, 0, 2 * Math.PI);
483
+ this.ctx.fill();
484
+
485
+ // Small white eye highlights
486
+ this.ctx.fillStyle = '#ffffff';
487
+ const highlightSize = eyeSize * 0.3;
488
+ this.ctx.beginPath();
489
+ this.ctx.arc(x + radius - eyeOffset + 1, y + radius - eyeOffset * 0.3 - 1, highlightSize, 0, 2 * Math.PI);
490
+ this.ctx.arc(x + radius + eyeOffset + 1, y + radius - eyeOffset * 0.3 - 1, highlightSize, 0, 2 * Math.PI);
491
+ this.ctx.fill();
492
+ } else {
493
+ // Body segments - simple rounded rectangles
494
+ this.ctx.fillStyle = '#8fbc8f';
495
+ this.ctx.beginPath();
496
+ this.ctx.roundRect(x, y, size, size, radius * 0.4);
497
+ this.ctx.fill();
498
+
499
+ // Simple scale pattern - just a small dot
500
+ this.ctx.fillStyle = '#689f38';
501
+ this.ctx.beginPath();
502
+ this.ctx.arc(x + radius, y + radius, Math.max(1, this.gridSize / 20), 0, 2 * Math.PI);
503
+ this.ctx.fill();
504
+ }
505
+ }
506
+
507
+ // Draw enhanced apple food
508
+ const foodX = this.food.x * this.gridSize + 8;
509
+ const foodY = this.food.y * this.gridSize + 8;
510
+ const appleSize = this.gridSize - 16;
511
+ const appleRadius = appleSize / 2;
512
+
513
+ // Apple body with gradient
514
+ const appleGradient = this.ctx.createRadialGradient(
515
+ foodX + appleRadius * 0.6, foodY + appleRadius * 0.6, 0,
516
+ foodX + appleRadius, foodY + appleRadius, appleRadius
517
+ );
518
+ appleGradient.addColorStop(0, '#ff6b6b');
519
+ appleGradient.addColorStop(1, '#e74c3c');
520
+ this.ctx.fillStyle = appleGradient;
521
+
522
+ this.ctx.beginPath();
523
+ this.ctx.arc(foodX + appleRadius, foodY + appleRadius, appleRadius, 0, 2 * Math.PI);
524
+ this.ctx.fill();
525
+
526
+ // Apple highlight
527
+ this.ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';
528
+ this.ctx.beginPath();
529
+ this.ctx.arc(foodX + appleRadius * 0.7, foodY + appleRadius * 0.7, appleRadius * 0.3, 0, 2 * Math.PI);
530
+ this.ctx.fill();
531
+
532
+ // Enhanced apple leaf
533
+ this.ctx.fillStyle = '#4caf50';
534
+ this.ctx.beginPath();
535
+ this.ctx.ellipse(foodX + appleRadius + 3, foodY + 3, 4, 8, -0.3, 0, 2 * Math.PI);
536
+ this.ctx.fill();
537
+
538
+ }
539
+
540
+ createSound(frequency, duration, type = 'sine') {
541
+ return { frequency, duration, type };
542
+ }
543
+
544
+ playSound(sound) {
545
+ try {
546
+ const audioContext = new (window.AudioContext || window.webkitAudioContext)();
547
+ const oscillator = audioContext.createOscillator();
548
+ const gainNode = audioContext.createGain();
549
+
550
+ oscillator.connect(gainNode);
551
+ gainNode.connect(audioContext.destination);
552
+
553
+ oscillator.frequency.setValueAtTime(sound.frequency, audioContext.currentTime);
554
+ oscillator.type = sound.type;
555
+
556
+ gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
557
+ gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + sound.duration);
558
+
559
+ oscillator.start(audioContext.currentTime);
560
+ oscillator.stop(audioContext.currentTime + sound.duration);
561
+ } catch (e) {
562
+ // Audio not supported or blocked
563
+ }
564
+ }
565
+
566
+ gameOver() {
567
+ this.gameRunning = false;
568
+
569
+ // Play game over sound
570
+ this.playSound(this.sounds.gameOver);
571
+
572
+ if (this.score > this.highScore) {
573
+ this.highScore = this.score;
574
+ localStorage.setItem('snakeHighScore', this.highScore);
575
+ this.highScoreElement.textContent = this.highScore;
576
+ }
577
+
578
+ this.finalScoreElement.textContent = this.score;
579
+ this.gameOverElement.style.display = 'block';
580
+ }
581
+
582
+ gameLoop(currentTime = 0) {
583
+ const deltaTime = currentTime - this.lastFrameTime;
584
+
585
+ if (deltaTime >= this.gameSpeed) {
586
+ this.update();
587
+ this.draw();
588
+ this.lastFrameTime = currentTime;
589
+ }
590
+
591
+ requestAnimationFrame((time) => this.gameLoop(time));
592
+ }
593
+ }
594
+
595
+ // Start the game when page loads
596
+ window.addEventListener('load', () => {
597
+ new SnakeGame();
598
+ });
599
+ </script>
600
+ </body>
601
+
602
+ </html>
Binary file
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "luvabase",
3
+ "version": "0.0.4",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "description": "Command line tool for Luvabase",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm --no-git-tag-version version patch && npm run build"
10
+ },
11
+ "dependencies": {
12
+ "@inquirer/prompts": "^5.3.8",
13
+ "commander": "^12.1.0",
14
+ "open": "^10.1.0"
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/index.js",
19
+ "types": "./dist/index.d.ts"
20
+ }
21
+ },
22
+ "bin": {
23
+ "luva": "dist/bin.js"
24
+ },
25
+ "devDependencies": {
26
+ "typescript": "^5.5.4"
27
+ }
28
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { program } from "commander"
4
+ import { readFileSync } from "fs"
5
+
6
+ const packageJson = JSON.parse(
7
+ readFileSync(new URL("../package.json", import.meta.url)).toString(),
8
+ )
9
+
10
+ program
11
+ .name("luva")
12
+ .description("Command line tool for Luvabase")
13
+ .version(packageJson.version)
14
+
15
+ program
16
+ .command("hello")
17
+ .description("Say hello")
18
+ .action(async () => {
19
+ console.log("Hello!")
20
+ })
21
+
22
+ program.parse()
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export function hello() {
2
+ return "Hello!"
3
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "sourceMap": true,
4
+ "module": "preserve",
5
+ "target": "es2022",
6
+ "strict": true,
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "skipLibCheck": true,
10
+ "esModuleInterop": true,
11
+ "outDir": "./dist"
12
+ },
13
+ "include": ["src/**/*.ts"]
14
+ }