termi-gotchi 1.0.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/dist/app.d.ts +6 -0
- package/dist/app.js +7 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +78 -0
- package/dist/logic.d.ts +19 -0
- package/dist/logic.js +30 -0
- package/dist/ui.d.ts +5 -0
- package/dist/ui.js +57 -0
- package/package.json +73 -0
- package/readme.md +57 -0
package/dist/app.d.ts
ADDED
package/dist/app.js
ADDED
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from 'ink';
|
|
3
|
+
import meow from 'meow';
|
|
4
|
+
import { App } from './ui.js';
|
|
5
|
+
import { getPet, feedPet } from './logic.js';
|
|
6
|
+
import { simpleGit } from 'simple-git';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
const cli = meow(`
|
|
10
|
+
Usage
|
|
11
|
+
$ termi-gotchi
|
|
12
|
+
|
|
13
|
+
Commands
|
|
14
|
+
feed Feed the pet (runs automatically by git hook)
|
|
15
|
+
init Install the git hook
|
|
16
|
+
|
|
17
|
+
Examples
|
|
18
|
+
$ termi-gotchi
|
|
19
|
+
$ termi-gotchi init
|
|
20
|
+
`, {
|
|
21
|
+
importMeta: import.meta,
|
|
22
|
+
});
|
|
23
|
+
const run = async () => {
|
|
24
|
+
const command = cli.input[0];
|
|
25
|
+
if (command === 'init') {
|
|
26
|
+
const gitHookPath = path.resolve(process.cwd(), '.git/hooks/post-commit');
|
|
27
|
+
// Check if .git exists
|
|
28
|
+
if (!fs.existsSync(path.resolve(process.cwd(), '.git'))) {
|
|
29
|
+
console.error('Error: Not a git repository. Run "git init" first.');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
const hookScript = `#!/bin/sh
|
|
33
|
+
# Run termi-gotchi after every commit
|
|
34
|
+
termi-gotchi feed
|
|
35
|
+
`;
|
|
36
|
+
fs.writeFileSync(gitHookPath, hookScript);
|
|
37
|
+
fs.chmodSync(gitHookPath, '755');
|
|
38
|
+
console.log("Git Hook Installed! Your pet is watching...");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (command === 'feed') {
|
|
42
|
+
const git = simpleGit();
|
|
43
|
+
try {
|
|
44
|
+
// Try to get diff from last commit
|
|
45
|
+
// If it's the first commit, HEAD^ might fail.
|
|
46
|
+
// basic try-catch for now.
|
|
47
|
+
let insertions = 0;
|
|
48
|
+
let deletions = 0;
|
|
49
|
+
try {
|
|
50
|
+
const diff = await git.diffSummary(['HEAD^', 'HEAD']);
|
|
51
|
+
insertions = diff.insertions;
|
|
52
|
+
deletions = diff.deletions;
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
// Fallback for first commit or other errors
|
|
56
|
+
// Maybe list files? For now, just give some default xp
|
|
57
|
+
insertions = 10;
|
|
58
|
+
}
|
|
59
|
+
const result = feedPet(insertions, deletions);
|
|
60
|
+
// We could just print a message, but rendering the App is cooler.
|
|
61
|
+
// Ideally we render it and then exit after a few seconds?
|
|
62
|
+
// Ink apps run until unmounted.
|
|
63
|
+
// We can just render it and let the user Ctrl+C or we can exit automatically.
|
|
64
|
+
// For post-commit hook, we probably want it to exit automatically.
|
|
65
|
+
// Let's pass a prop to App to auto-exit? Or just handle it here.
|
|
66
|
+
const { unmount } = render(React.createElement(App, { pet: result }));
|
|
67
|
+
setTimeout(() => unmount(), 2500);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
console.error("Error feeding pet:", e);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Default: Show status
|
|
75
|
+
const pet = getPet();
|
|
76
|
+
render(React.createElement(App, { pet: pet }));
|
|
77
|
+
};
|
|
78
|
+
run();
|
package/dist/logic.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface PetState {
|
|
2
|
+
name: string;
|
|
3
|
+
level: number;
|
|
4
|
+
xp: number;
|
|
5
|
+
health: number;
|
|
6
|
+
lastFed: string;
|
|
7
|
+
poopCount: number;
|
|
8
|
+
event?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const getPet: () => PetState;
|
|
11
|
+
export declare const feedPet: (linesAdded: number, linesDeleted: number) => {
|
|
12
|
+
event: string;
|
|
13
|
+
name: string;
|
|
14
|
+
level: number;
|
|
15
|
+
xp: number;
|
|
16
|
+
health: number;
|
|
17
|
+
lastFed: string;
|
|
18
|
+
poopCount: number;
|
|
19
|
+
};
|
package/dist/logic.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Conf from 'conf';
|
|
2
|
+
const config = new Conf({
|
|
3
|
+
projectName: 'termi-gotchi',
|
|
4
|
+
defaults: {
|
|
5
|
+
name: 'Git-Mon',
|
|
6
|
+
level: 1,
|
|
7
|
+
xp: 0,
|
|
8
|
+
health: 100,
|
|
9
|
+
lastFed: new Date().toISOString(),
|
|
10
|
+
poopCount: 0
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
export const getPet = () => config.store;
|
|
14
|
+
export const feedPet = (linesAdded, linesDeleted) => {
|
|
15
|
+
const pet = getPet();
|
|
16
|
+
// Logic: deletions are better (refactoring)
|
|
17
|
+
const nutrition = (linesAdded * 0.1) + (linesDeleted * 0.5);
|
|
18
|
+
pet.xp += nutrition;
|
|
19
|
+
pet.health = Math.min(100, pet.health + 10);
|
|
20
|
+
pet.lastFed = new Date().toISOString();
|
|
21
|
+
let event = 'EATING';
|
|
22
|
+
// Level up logic
|
|
23
|
+
if (pet.xp > pet.level * 50) {
|
|
24
|
+
pet.level++;
|
|
25
|
+
pet.xp = 0;
|
|
26
|
+
event = 'LEVEL_UP';
|
|
27
|
+
}
|
|
28
|
+
config.set(pet);
|
|
29
|
+
return { ...pet, event };
|
|
30
|
+
};
|
package/dist/ui.d.ts
ADDED
package/dist/ui.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import Gradient from 'ink-gradient';
|
|
4
|
+
import BigText from 'ink-big-text';
|
|
5
|
+
const PetAvatar = ({ mood }) => {
|
|
6
|
+
if (mood === 'happy') {
|
|
7
|
+
return (React.createElement(Box, { borderStyle: "round", borderColor: "green", padding: 1 },
|
|
8
|
+
React.createElement(Text, null,
|
|
9
|
+
"( ^_^) ",
|
|
10
|
+
"\n",
|
|
11
|
+
"( ",
|
|
12
|
+
'>',
|
|
13
|
+
"\u2615",
|
|
14
|
+
'<',
|
|
15
|
+
" )")));
|
|
16
|
+
}
|
|
17
|
+
if (mood === 'hungry') {
|
|
18
|
+
return (React.createElement(Box, { borderStyle: "double", borderColor: "red", padding: 1 },
|
|
19
|
+
React.createElement(Text, null,
|
|
20
|
+
"( 0_0 ) ",
|
|
21
|
+
"\n",
|
|
22
|
+
"( ",
|
|
23
|
+
'>',
|
|
24
|
+
"\uD83C\uDF55",
|
|
25
|
+
'<',
|
|
26
|
+
" ) ?")));
|
|
27
|
+
}
|
|
28
|
+
return React.createElement(Text, null, "( -_- ) Zzz...");
|
|
29
|
+
};
|
|
30
|
+
export const App = ({ pet }) => {
|
|
31
|
+
const now = new Date();
|
|
32
|
+
const lastFedDate = new Date(pet.lastFed);
|
|
33
|
+
const diffHours = (now.getTime() - lastFedDate.getTime()) / (1000 * 60 * 60);
|
|
34
|
+
const mood = diffHours > 4 ? 'hungry' : 'happy';
|
|
35
|
+
return (React.createElement(Box, { flexDirection: "column", alignItems: "center" },
|
|
36
|
+
React.createElement(Gradient, { name: "pastel" },
|
|
37
|
+
React.createElement(BigText, { text: "Termi-Gotchi" })),
|
|
38
|
+
React.createElement(PetAvatar, { mood: mood }),
|
|
39
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column", alignItems: "center" },
|
|
40
|
+
React.createElement(Text, { color: "green" },
|
|
41
|
+
"Lvl ",
|
|
42
|
+
pet.level,
|
|
43
|
+
" ",
|
|
44
|
+
pet.name),
|
|
45
|
+
React.createElement(Text, null,
|
|
46
|
+
"XP: ",
|
|
47
|
+
pet.xp.toFixed(1),
|
|
48
|
+
" / ",
|
|
49
|
+
pet.level * 50),
|
|
50
|
+
React.createElement(Text, { color: mood === 'hungry' ? 'red' : 'green' },
|
|
51
|
+
"Status: ",
|
|
52
|
+
mood.toUpperCase()),
|
|
53
|
+
React.createElement(Text, null,
|
|
54
|
+
"Health: ",
|
|
55
|
+
pet.health,
|
|
56
|
+
"%"))));
|
|
57
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "termi-gotchi",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A CLI Tamagotchi that eats your code commits",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "MdShahAmanPatwary",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/TAIJULAMAN/Termi-Gotchi"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"cli",
|
|
13
|
+
"tamagotchi",
|
|
14
|
+
"git",
|
|
15
|
+
"gamification",
|
|
16
|
+
"ink"
|
|
17
|
+
],
|
|
18
|
+
"bin": "dist/cli.js",
|
|
19
|
+
"type": "module",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=16"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc",
|
|
25
|
+
"dev": "tsc --watch",
|
|
26
|
+
"test": "prettier --check . && xo && ava"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"conf": "^15.1.0",
|
|
33
|
+
"ink": "^4.1.0",
|
|
34
|
+
"ink-big-text": "^2.0.0",
|
|
35
|
+
"ink-gradient": "^4.0.0",
|
|
36
|
+
"meow": "^11.0.0",
|
|
37
|
+
"react": "^18.2.0",
|
|
38
|
+
"simple-git": "^3.30.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@sindresorhus/tsconfig": "^3.0.1",
|
|
42
|
+
"@types/node": "^25.2.2",
|
|
43
|
+
"@types/react": "^18.0.32",
|
|
44
|
+
"@vdemedes/prettier-config": "^2.0.1",
|
|
45
|
+
"ava": "^5.2.0",
|
|
46
|
+
"chalk": "^5.6.2",
|
|
47
|
+
"eslint-config-xo-react": "^0.27.0",
|
|
48
|
+
"eslint-plugin-react": "^7.32.2",
|
|
49
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
50
|
+
"ink-testing-library": "^3.0.0",
|
|
51
|
+
"prettier": "^2.8.7",
|
|
52
|
+
"ts-node": "^10.9.1",
|
|
53
|
+
"typescript": "^5.0.3",
|
|
54
|
+
"xo": "^0.53.1"
|
|
55
|
+
},
|
|
56
|
+
"ava": {
|
|
57
|
+
"extensions": {
|
|
58
|
+
"ts": "module",
|
|
59
|
+
"tsx": "module"
|
|
60
|
+
},
|
|
61
|
+
"nodeArguments": [
|
|
62
|
+
"--loader=ts-node/esm"
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
"xo": {
|
|
66
|
+
"extends": "xo-react",
|
|
67
|
+
"prettier": true,
|
|
68
|
+
"rules": {
|
|
69
|
+
"react/prop-types": "off"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"prettier": "@vdemedes/prettier-config"
|
|
73
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Termi-Gotchi
|
|
2
|
+
|
|
3
|
+
A CLI Tamagotchi that lives in your terminal and eats your code commits!
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Clone the repository
|
|
9
|
+
git clone <repo-url>
|
|
10
|
+
cd termi-gotchi
|
|
11
|
+
|
|
12
|
+
# Install dependencies
|
|
13
|
+
npm install
|
|
14
|
+
|
|
15
|
+
# Build the project
|
|
16
|
+
npm run build
|
|
17
|
+
|
|
18
|
+
# Link globally (optional, but recommended for CLI usage)
|
|
19
|
+
npm link
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### 1. Initialize Git Hook
|
|
25
|
+
Run this in any git repository where you want your pet to live:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
termi-gotchi init
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This installs a `post-commit` hook that will feed your pet automatically.
|
|
32
|
+
|
|
33
|
+
### 2. Feed Your Pet
|
|
34
|
+
Just commit code!
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git commit -m "Fix bug"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Your pet will appear briefly, eat the commit, and gain XP based on lines added/deleted. Refactoring (deleting lines) gives more XP!
|
|
41
|
+
|
|
42
|
+
### 3. Check Status manually
|
|
43
|
+
You can check on your pet anytime:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
termi-gotchi
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
- **Hunger System**: Your pet gets hungry if you don't commit for 4 hours.
|
|
51
|
+
- **Level Up**: Gain XP to level up your pet.
|
|
52
|
+
- **Moods**: Happy, Hungry, Sleeping.
|
|
53
|
+
|
|
54
|
+
## Technologies
|
|
55
|
+
- [Ink](https://github.com/vadimdemedes/ink) (React for CLI)
|
|
56
|
+
- `conf` for state persistence
|
|
57
|
+
- `simple-git` for git integration
|