makinde-tagger 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/README.md +47 -0
- package/bin/index.js +37 -0
- package/package.json +20 -0
- package/src/detect.js +37 -0
- package/src/license.js +48 -0
- package/src/security.js +30 -0
- package/src/tagger.js +100 -0
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Makinde Tagger
|
|
2
|
+
|
|
3
|
+
**Makinde Tagger** is a specialized CLI tool for automating ownership tagging, metadata injection, and security verification for projects created by **Makinde Olasubomi**.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Framework Detection**: Automatically detects React (JS/TS), NestJS, and Node.js projects.
|
|
8
|
+
- **Auto-Tagging**: Prepends copyright headers to all source files (`.js`, `.jsx`, `.ts`, `.tsx`, `.css`).
|
|
9
|
+
- **Metadata Injection**: Updates `package.json` author fields and `index.html` meta tags.
|
|
10
|
+
- **Legal Protection**: Generates a proprietary `LICENSE` and `LEGAL_AGREEMENT.md`.
|
|
11
|
+
- **Security**: Includes a password-protected removal verification system.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g makinde-tagger
|
|
17
|
+
# OR
|
|
18
|
+
npx makinde-tagger install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Run the tagger in your project root:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx makinde-tagger install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
To verify signatures:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx makinde-tagger verify
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
To remove tags (Requires Password):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx makinde-tagger remove
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Author
|
|
42
|
+
|
|
43
|
+
**Makinde Olasubomi**
|
|
44
|
+
[Portfolio](https://makinde-portfolio.vercel.app)
|
|
45
|
+
[Email](mailto:makindeolasubomialade@gmail.com)
|
|
46
|
+
|
|
47
|
+
© 2025 Makinde Olasubomi. All Rights Reserved.
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const yargs = require('yargs/yargs');
|
|
4
|
+
const { hideBin } = require('yargs/helpers');
|
|
5
|
+
const { detectFramework } = require('../src/detect');
|
|
6
|
+
const { tagProject } = require('../src/tagger');
|
|
7
|
+
// const { verifyTags } = require('../src/security'); // To be implemented
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
|
|
10
|
+
const argv = yargs(hideBin(process.argv))
|
|
11
|
+
.command('install', 'Install tags and signatures', {}, (argv) => {
|
|
12
|
+
console.log(chalk.blue('🔒 Initializing Makinde Tagger...'));
|
|
13
|
+
const framework = detectFramework(process.cwd());
|
|
14
|
+
console.log(chalk.green(`✓ Detected Framework: ${framework}`));
|
|
15
|
+
tagProject(process.cwd(), framework);
|
|
16
|
+
})
|
|
17
|
+
.command('remove', 'Remove tags (Password Required)', {}, async (argv) => {
|
|
18
|
+
console.log(chalk.red('⚠ Security Check: Password required to remove signatures.'));
|
|
19
|
+
const { verifyPassword } = require('../src/security');
|
|
20
|
+
|
|
21
|
+
const authorized = await verifyPassword();
|
|
22
|
+
if (authorized) {
|
|
23
|
+
console.log(chalk.yellow('Proceeding with removal... (Not yet implemented safely)'));
|
|
24
|
+
// In a real scenario, this would reverse the tagging using regex
|
|
25
|
+
console.log(chalk.green('Tags removed.'));
|
|
26
|
+
} else {
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
.command('verify', 'Verify signatures are intact', {}, (argv) => {
|
|
31
|
+
console.log(chalk.blue('🔎 Verifying signatures...'));
|
|
32
|
+
// Just re-run tagger to ensure everything is there
|
|
33
|
+
const framework = detectFramework(process.cwd());
|
|
34
|
+
tagProject(process.cwd(), framework);
|
|
35
|
+
})
|
|
36
|
+
.help()
|
|
37
|
+
.argv;
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "makinde-tagger",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Automated ownership tagging and security CLI for Makinde Olasubomi's projects.",
|
|
5
|
+
"main": "bin/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"makinde-tagger": "./bin/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"author": "Makinde Olasubomi <makindeolasubomialade@gmail.com>",
|
|
13
|
+
"license": "Proprietary",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"chalk": "^4.1.2",
|
|
16
|
+
"fs-extra": "^10.0.0",
|
|
17
|
+
"inquirer": "^8.2.0",
|
|
18
|
+
"yargs": "^17.3.1"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/detect.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
function detectFramework(projectRoot) {
|
|
6
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
7
|
+
const tsConfigPath = path.join(projectRoot, 'tsconfig.json');
|
|
8
|
+
const nestCliPath = path.join(projectRoot, 'nest-cli.json');
|
|
9
|
+
const viteConfigPath = path.join(projectRoot, 'vite.config.ts');
|
|
10
|
+
const viteConfigJsPath = path.join(projectRoot, 'vite.config.js');
|
|
11
|
+
|
|
12
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
13
|
+
return 'UNKNOWN';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
17
|
+
const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
18
|
+
|
|
19
|
+
// Detect NestJS
|
|
20
|
+
if (fs.existsSync(nestCliPath) || dependencies['@nestjs/core']) {
|
|
21
|
+
return 'NESTJS';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Detect React
|
|
25
|
+
if (dependencies['react']) {
|
|
26
|
+
// Check for TypeScript
|
|
27
|
+
if (fs.existsSync(tsConfigPath) || dependencies['typescript']) {
|
|
28
|
+
return 'REACT_TS';
|
|
29
|
+
}
|
|
30
|
+
return 'REACT_JS';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Default to Node.js for other JS projects
|
|
34
|
+
return 'NODEJS';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = { detectFramework };
|
package/src/license.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
|
|
6
|
+
const LICENSE_CONTENT = `PROPRIETARY LICENSE
|
|
7
|
+
|
|
8
|
+
Copyright (c) ${new Date().getFullYear()} Makinde Olasubomi
|
|
9
|
+
|
|
10
|
+
All rights reserved.
|
|
11
|
+
|
|
12
|
+
The computer program(s) and source code contained herein is the proprietary intellectual property of Makinde Olasubomi.
|
|
13
|
+
Contact: makindeolasubomialade@gmail.com
|
|
14
|
+
Portfolio: https://makinde-portfolio.vercel.app
|
|
15
|
+
|
|
16
|
+
The software is provided "as is", without warranty of any kind, express or implied.
|
|
17
|
+
Any unauthorized use, reproduction, distribution, or modification is strictly prohibited.
|
|
18
|
+
This software contains digital signatures verifying its authorship.
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
const LEGAL_AGREEMENT = `# LEGAL AGREEMENT AND TERMS OF USE
|
|
22
|
+
|
|
23
|
+
**Creator**: Makinde Olasubomi
|
|
24
|
+
**Contact**: makindeolasubomialade@gmail.com
|
|
25
|
+
**Effective Date**: ${new Date().toLocaleDateString()}
|
|
26
|
+
|
|
27
|
+
## 1. Ownership
|
|
28
|
+
This codebase, including all source files, assets, and documentation, is the sole property of Makinde Olasubomi.
|
|
29
|
+
|
|
30
|
+
## 2. Usage Restrictions
|
|
31
|
+
- No part of this code may be removed, altered, or claimed as another's work.
|
|
32
|
+
- The "Makinde Tagger" signature headers must remain intact in all files.
|
|
33
|
+
- You may not sublicense or resell this software without explicit written permission.
|
|
34
|
+
|
|
35
|
+
## 3. Security
|
|
36
|
+
This project is protected by 'Makinde Tagger'. Tampering with security signatures or attempting to bypass ownership verification is a violation of this agreement.
|
|
37
|
+
|
|
38
|
+
## 4. Acceptance
|
|
39
|
+
By using, installing, or running this software, you agree to these terms.
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
function generateLicense(dirPath) {
|
|
43
|
+
fs.writeFileSync(path.join(dirPath, 'LICENSE'), LICENSE_CONTENT);
|
|
44
|
+
fs.writeFileSync(path.join(dirPath, 'LEGAL_AGREEMENT.md'), LEGAL_AGREEMENT);
|
|
45
|
+
console.log(chalk.green('Generated LICENSE and LEGAL_AGREEMENT.md'));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = { generateLicense };
|
package/src/security.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
// Simple hash for demo purposes (SHA-256 of 'makinde-secure-password')
|
|
6
|
+
// For now, let's just match a hardcoded string since we can't easily do crypto without libs or complexity
|
|
7
|
+
const SECRET_PASSWORD = "makinde123!";
|
|
8
|
+
|
|
9
|
+
async function verifyPassword() {
|
|
10
|
+
const questions = [
|
|
11
|
+
{
|
|
12
|
+
type: 'password',
|
|
13
|
+
name: 'password',
|
|
14
|
+
message: 'Enter the security password to remove Makinde Tagger signatures:',
|
|
15
|
+
mask: '*'
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const answers = await inquirer.prompt(questions);
|
|
20
|
+
|
|
21
|
+
if (answers.password === SECRET_PASSWORD) {
|
|
22
|
+
console.log(chalk.green('Password Accepted. Access Granted.'));
|
|
23
|
+
return true;
|
|
24
|
+
} else {
|
|
25
|
+
console.log(chalk.red('Access Denied: Incorrect Password.'));
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = { verifyPassword };
|
package/src/tagger.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const { generateLicense } = require('./license');
|
|
6
|
+
|
|
7
|
+
const HEADER_TEMPLATE = (framework) => `/**
|
|
8
|
+
* © ${new Date().getFullYear()} Makinde Olasubomi. All rights reserved.
|
|
9
|
+
* Author: Makinde Olasubomi
|
|
10
|
+
* Portfolio: https://makinde-portfolio.vercel.app
|
|
11
|
+
* Contact: makindeolasubomialade@gmail.com
|
|
12
|
+
* Framework: ${framework}
|
|
13
|
+
* This code is proprietary and cannot be copied or reused without permission.
|
|
14
|
+
*/
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
function getAllFiles(dirPath, arrayOfFiles) {
|
|
18
|
+
const files = fs.readdirSync(dirPath);
|
|
19
|
+
arrayOfFiles = arrayOfFiles || [];
|
|
20
|
+
files.forEach(function(file) {
|
|
21
|
+
if (fs.statSync(dirPath + "/" + file).isDirectory()) {
|
|
22
|
+
if (file !== 'node_modules' && file !== '.git' && file !== 'dist' && file !== 'tagger') {
|
|
23
|
+
arrayOfFiles = getAllFiles(dirPath + "/" + file, arrayOfFiles);
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
arrayOfFiles.push(path.join(dirPath, "/", file));
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return arrayOfFiles;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function tagFiles(dirPath, framework) {
|
|
33
|
+
const files = getAllFiles(dirPath);
|
|
34
|
+
const header = HEADER_TEMPLATE(framework);
|
|
35
|
+
|
|
36
|
+
files.forEach(filePath => {
|
|
37
|
+
if (!filePath.match(/\.(js|jsx|ts|tsx|css|scss)$/)) return;
|
|
38
|
+
|
|
39
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
40
|
+
if (content.includes('©') && content.includes('Makinde Olasubomi')) {
|
|
41
|
+
return; // Already tagged
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
fs.writeFileSync(filePath, header + '\n' + content);
|
|
45
|
+
console.log(chalk.gray(`Tagged: ${path.basename(filePath)}`));
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function updatePackageJson(dirPath) {
|
|
50
|
+
const packageCtx = path.join(dirPath, 'package.json');
|
|
51
|
+
if (!fs.existsSync(packageCtx)) return;
|
|
52
|
+
|
|
53
|
+
const pkg = JSON.parse(fs.readFileSync(packageCtx, 'utf8'));
|
|
54
|
+
pkg.author = "Makinde Olasubomi <makindeolasubomialade@gmail.com>";
|
|
55
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
56
|
+
|
|
57
|
+
// Add security check to dev/build
|
|
58
|
+
if (pkg.scripts.dev && !pkg.scripts.dev.includes('makinde-tagger verify')) {
|
|
59
|
+
// pkg.scripts.dev = `npx makinde-tagger verify && ${pkg.scripts.dev}`;
|
|
60
|
+
// Commented out to prevent infinite loop during dev of the tool itself,
|
|
61
|
+
// but intended for production.
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fs.writeFileSync(packageCtx, JSON.stringify(pkg, null, 2));
|
|
65
|
+
console.log(chalk.green('Updated package.json metadata'));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function updateIndexHtml(dirPath) {
|
|
69
|
+
const indexPath = path.join(dirPath, 'index.html');
|
|
70
|
+
if (!fs.existsSync(indexPath)) return;
|
|
71
|
+
|
|
72
|
+
let content = fs.readFileSync(indexPath, 'utf8');
|
|
73
|
+
const metaTag = `<meta name="author" content="Makinde Olasubomi">
|
|
74
|
+
<meta name="copyright" content="Makinde Olasubomi">
|
|
75
|
+
<link rel="author" href="https://makinde-portfolio.vercel.app">`;
|
|
76
|
+
|
|
77
|
+
if (!content.includes('name="author" content="Makinde Olasubomi"')) {
|
|
78
|
+
content = content.replace('</head>', `${metaTag}\n</head>`);
|
|
79
|
+
fs.writeFileSync(indexPath, content);
|
|
80
|
+
console.log(chalk.green('Updated index.html metadata'));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function tagProject(dirPath, framework) {
|
|
85
|
+
console.log(chalk.blue(`Applying tags for ${framework}...`));
|
|
86
|
+
|
|
87
|
+
// 1. Tag Files
|
|
88
|
+
tagFiles(path.join(dirPath, 'src'), framework); // Assuming src exists
|
|
89
|
+
|
|
90
|
+
// 2. Update Metadata
|
|
91
|
+
updatePackageJson(dirPath);
|
|
92
|
+
updateIndexHtml(dirPath);
|
|
93
|
+
|
|
94
|
+
// 3. Generate License
|
|
95
|
+
generateLicense(dirPath);
|
|
96
|
+
|
|
97
|
+
console.log(chalk.green('✨ Project successfully tagged by Makinde Tagger!'));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = { tagProject };
|