apikeyscreator 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.
@@ -0,0 +1,143 @@
1
+ import express from 'express';
2
+ import { db } from '../utils/db.js';
3
+
4
+ export const apiKeysRoutes = express.Router();
5
+
6
+ // List all API keys for user
7
+ apiKeysRoutes.get('/', (req, res) => {
8
+ const keys = db.keys.findByUserId(req.user.userId);
9
+
10
+ return res.json({
11
+ message: 'API keys retrieved successfully',
12
+ count: keys.length,
13
+ keys: keys.map(k => ({
14
+ id: k.id,
15
+ name: k.name,
16
+ key: k.key.substring(0, 10) + '...' + k.key.substring(k.key.length - 4),
17
+ fullKey: k.key,
18
+ active: k.active,
19
+ createdAt: k.createdAt,
20
+ lastUsed: k.lastUsed,
21
+ })),
22
+ });
23
+ });
24
+
25
+ // Get single API key
26
+ apiKeysRoutes.get('/:id', (req, res) => {
27
+ const keyId = req.params.id;
28
+
29
+ const key = db.keys.findById(req.user.userId, keyId);
30
+ if (!key) {
31
+ return res.status(404).json({ error: 'API key not found' });
32
+ }
33
+
34
+ return res.json({
35
+ message: 'API key retrieved successfully',
36
+ key: {
37
+ id: key.id,
38
+ name: key.name,
39
+ key: key.key.substring(0, 10) + '...' + key.key.substring(key.key.length - 4),
40
+ fullKey: key.key,
41
+ active: key.active,
42
+ createdAt: key.createdAt,
43
+ lastUsed: key.lastUsed,
44
+ },
45
+ });
46
+ });
47
+
48
+ // Create new API key
49
+ apiKeysRoutes.post('/', async (req, res) => {
50
+ try {
51
+ const { name } = req.body;
52
+
53
+ if (!name) {
54
+ return res.status(400).json({
55
+ error: 'Key name is required'
56
+ });
57
+ }
58
+
59
+ const newKey = db.keys.create(req.user.userId, name);
60
+
61
+ return res.status(201).json({
62
+ message: 'API key created successfully',
63
+ key: {
64
+ id: newKey.id,
65
+ name: newKey.name,
66
+ key: newKey.key,
67
+ active: newKey.active,
68
+ createdAt: newKey.createdAt,
69
+ },
70
+ });
71
+ } catch (error) {
72
+ return res.status(500).json({
73
+ error: error.message
74
+ });
75
+ }
76
+ });
77
+
78
+ // Update API key (name, status)
79
+ apiKeysRoutes.put('/:id', async (req, res) => {
80
+ try {
81
+ const keyId = req.params.id;
82
+ const { name, active } = req.body;
83
+
84
+ const key = db.keys.findById(req.user.userId, keyId);
85
+ if (!key) {
86
+ return res.status(404).json({ error: 'API key not found' });
87
+ }
88
+
89
+ const updates = {};
90
+ if (name !== undefined) updates.name = name;
91
+ if (active !== undefined) updates.active = active;
92
+
93
+ const updatedKey = db.keys.update(req.user.userId, keyId, updates);
94
+
95
+ return res.json({
96
+ message: 'API key updated successfully',
97
+ key: {
98
+ id: updatedKey.id,
99
+ name: updatedKey.name,
100
+ key: updatedKey.key.substring(0, 10) + '...' + updatedKey.key.substring(updatedKey.key.length - 4),
101
+ active: updatedKey.active,
102
+ createdAt: updatedKey.createdAt,
103
+ lastUsed: updatedKey.lastUsed,
104
+ },
105
+ });
106
+ } catch (error) {
107
+ return res.status(500).json({
108
+ error: error.message
109
+ });
110
+ }
111
+ });
112
+
113
+ // Delete API key
114
+ apiKeysRoutes.delete('/:id', (req, res) => {
115
+ const keyId = req.params.id;
116
+
117
+ const key = db.keys.findById(req.user.userId, keyId);
118
+ if (!key) {
119
+ return res.status(404).json({ error: 'API key not found' });
120
+ }
121
+
122
+ db.keys.delete(req.user.userId, keyId);
123
+
124
+ return res.json({
125
+ message: 'API key deleted successfully',
126
+ });
127
+ });
128
+
129
+ // Record key usage
130
+ apiKeysRoutes.post('/:id/usage', (req, res) => {
131
+ const keyId = req.params.id;
132
+
133
+ const key = db.keys.findById(req.user.userId, keyId);
134
+ if (!key) {
135
+ return res.status(404).json({ error: 'API key not found' });
136
+ }
137
+
138
+ db.keys.recordUsage(req.user.userId, keyId);
139
+
140
+ return res.json({
141
+ message: 'API key usage recorded',
142
+ });
143
+ });
@@ -0,0 +1,96 @@
1
+ import express from 'express';
2
+ import bcrypt from 'bcryptjs';
3
+ import { db } from '../utils/db.js';
4
+ import { generateToken } from '../utils/jwt.js';
5
+
6
+ export const authRoutes = express.Router();
7
+
8
+ // Register
9
+ authRoutes.post('/register', async (req, res) => {
10
+ try {
11
+ const { email, password } = req.body;
12
+
13
+ if (!email || !password) {
14
+ return res.status(400).json({
15
+ error: 'Email and password are required'
16
+ });
17
+ }
18
+
19
+ const existingUser = db.users.findByEmail(email);
20
+ if (existingUser) {
21
+ return res.status(409).json({
22
+ error: 'User already exists'
23
+ });
24
+ }
25
+
26
+ const hashedPassword = await bcrypt.hash(password, 10);
27
+ const user = db.users.create(email, hashedPassword);
28
+
29
+ const token = generateToken(user.id, user.email);
30
+
31
+ return res.status(201).json({
32
+ message: 'User registered successfully',
33
+ user: { id: user.id, email: user.email },
34
+ token,
35
+ });
36
+ } catch (error) {
37
+ return res.status(500).json({
38
+ error: error.message
39
+ });
40
+ }
41
+ });
42
+
43
+ // Login
44
+ authRoutes.post('/login', async (req, res) => {
45
+ try {
46
+ const { email, password } = req.body;
47
+
48
+ if (!email || !password) {
49
+ return res.status(400).json({
50
+ error: 'Email and password are required'
51
+ });
52
+ }
53
+
54
+ const user = db.users.findByEmail(email);
55
+ if (!user) {
56
+ return res.status(401).json({
57
+ error: 'Invalid email or password'
58
+ });
59
+ }
60
+
61
+ const isPasswordValid = await bcrypt.compare(password, user.password);
62
+ if (!isPasswordValid) {
63
+ return res.status(401).json({
64
+ error: 'Invalid email or password'
65
+ });
66
+ }
67
+
68
+ const token = generateToken(user.id, user.email);
69
+
70
+ return res.json({
71
+ message: 'Login successful',
72
+ user: { id: user.id, email: user.email },
73
+ token,
74
+ });
75
+ } catch (error) {
76
+ return res.status(500).json({
77
+ error: error.message
78
+ });
79
+ }
80
+ });
81
+
82
+ // Get current user
83
+ authRoutes.get('/me', (req, res) => {
84
+ const token = req.headers['authorization']?.split(' ')[1];
85
+
86
+ if (!token) {
87
+ return res.status(401).json({ error: 'Missing authorization token' });
88
+ }
89
+
90
+ const user = db.users.findByEmail(req.query.email);
91
+
92
+ return res.json({
93
+ message: 'User retrieved successfully',
94
+ user: user ? { id: user.id, email: user.email } : null,
95
+ });
96
+ });
package/src/server.js ADDED
@@ -0,0 +1,41 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import { authMiddleware } from './middleware/auth.js';
4
+ import { apiKeysRoutes } from './routes/apiKeys.js';
5
+ import { authRoutes } from './routes/auth.js';
6
+
7
+ const app = express();
8
+
9
+ app.use(express.json());
10
+ app.use(cors());
11
+
12
+ // Health check
13
+ app.get('/', (req, res) => {
14
+ res.json({ message: 'API Keys Creator System running' });
15
+ });
16
+
17
+ // Public auth routes
18
+ app.use('/auth', authRoutes);
19
+
20
+ // Protected API routes
21
+ app.use('/api/keys', authMiddleware, apiKeysRoutes);
22
+
23
+ // Error handling
24
+ app.use((err, req, res, next) => {
25
+ console.error('Error:', err);
26
+ res.status(err.status || 500).json({
27
+ error: err.message || 'Internal Server Error',
28
+ code: err.code || 'INTERNAL_ERROR'
29
+ });
30
+ });
31
+
32
+ // 404 handler
33
+ app.use((req, res) => {
34
+ res.status(404).json({ error: 'Not Found' });
35
+ });
36
+
37
+ const PORT = process.env.PORT || 3000;
38
+
39
+ app.listen(PORT, () => {
40
+ console.log(`โœ“ API Keys Creator System running on http://localhost:${PORT}`);
41
+ });
@@ -0,0 +1,137 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ const USERS_DB = path.join(__dirname, '../data/users.json');
7
+ const KEYS_DB = path.join(__dirname, '../data/keys.json');
8
+
9
+ const ensureDir = () => {
10
+ const dir = path.dirname(USERS_DB);
11
+ if (!fs.existsSync(dir)) {
12
+ fs.mkdirSync(dir, { recursive: true });
13
+ }
14
+ };
15
+
16
+ const ensureFile = (filepath, defaultContent = {}) => {
17
+ ensureDir();
18
+ if (!fs.existsSync(filepath)) {
19
+ fs.writeFileSync(filepath, JSON.stringify(defaultContent, null, 2));
20
+ }
21
+ };
22
+
23
+ export const db = {
24
+ users: {
25
+ readAll: () => {
26
+ ensureFile(USERS_DB, {});
27
+ const data = fs.readFileSync(USERS_DB, 'utf-8');
28
+ return JSON.parse(data);
29
+ },
30
+
31
+ write: (users) => {
32
+ ensureFile(USERS_DB, {});
33
+ fs.writeFileSync(USERS_DB, JSON.stringify(users, null, 2));
34
+ },
35
+
36
+ findByEmail: (email) => {
37
+ const users = db.users.readAll();
38
+ return users[email];
39
+ },
40
+
41
+ create: (email, hashedPassword) => {
42
+ const users = db.users.readAll();
43
+ const userId = Date.now().toString();
44
+ users[email] = {
45
+ id: userId,
46
+ email,
47
+ password: hashedPassword,
48
+ createdAt: new Date().toISOString(),
49
+ };
50
+ db.users.write(users);
51
+ return users[email];
52
+ },
53
+ },
54
+
55
+ keys: {
56
+ readAll: () => {
57
+ ensureFile(KEYS_DB, {});
58
+ const data = fs.readFileSync(KEYS_DB, 'utf-8');
59
+ return JSON.parse(data);
60
+ },
61
+
62
+ write: (keys) => {
63
+ ensureFile(KEYS_DB, {});
64
+ fs.writeFileSync(KEYS_DB, JSON.stringify(keys, null, 2));
65
+ },
66
+
67
+ create: (userId, keyName) => {
68
+ const keys = db.keys.readAll();
69
+ const keyId = Date.now().toString();
70
+
71
+ if (!keys[userId]) {
72
+ keys[userId] = [];
73
+ }
74
+
75
+ const newKey = {
76
+ id: keyId,
77
+ name: keyName,
78
+ key: `sk_${Math.random().toString(36).substr(2, 32)}`,
79
+ createdAt: new Date().toISOString(),
80
+ lastUsed: null,
81
+ active: true,
82
+ };
83
+
84
+ keys[userId].push(newKey);
85
+ db.keys.write(keys);
86
+
87
+ return newKey;
88
+ },
89
+
90
+ findByUserId: (userId) => {
91
+ const keys = db.keys.readAll();
92
+ return keys[userId] || [];
93
+ },
94
+
95
+ findById: (userId, keyId) => {
96
+ const userKeys = db.keys.findByUserId(userId);
97
+ return userKeys.find(k => k.id === keyId);
98
+ },
99
+
100
+ update: (userId, keyId, updates) => {
101
+ const keys = db.keys.readAll();
102
+ if (!keys[userId]) return null;
103
+
104
+ const keyIndex = keys[userId].findIndex(k => k.id === keyId);
105
+ if (keyIndex === -1) return null;
106
+
107
+ keys[userId][keyIndex] = {
108
+ ...keys[userId][keyIndex],
109
+ ...updates,
110
+ };
111
+
112
+ db.keys.write(keys);
113
+ return keys[userId][keyIndex];
114
+ },
115
+
116
+ delete: (userId, keyId) => {
117
+ const keys = db.keys.readAll();
118
+ if (!keys[userId]) return false;
119
+
120
+ const initialLength = keys[userId].length;
121
+ keys[userId] = keys[userId].filter(k => k.id !== keyId);
122
+
123
+ if (keys[userId].length < initialLength) {
124
+ db.keys.write(keys);
125
+ return true;
126
+ }
127
+
128
+ return false;
129
+ },
130
+
131
+ recordUsage: (userId, keyId) => {
132
+ return db.keys.update(userId, keyId, {
133
+ lastUsed: new Date().toISOString(),
134
+ });
135
+ },
136
+ },
137
+ };
@@ -0,0 +1,24 @@
1
+ import jwt from 'jsonwebtoken';
2
+
3
+ const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
4
+ const TOKEN_EXPIRY = '24h';
5
+
6
+ export const generateToken = (userId, email) => {
7
+ return jwt.sign(
8
+ { userId, email },
9
+ JWT_SECRET,
10
+ { expiresIn: TOKEN_EXPIRY }
11
+ );
12
+ };
13
+
14
+ export const verifyToken = (token) => {
15
+ try {
16
+ return jwt.verify(token, JWT_SECRET);
17
+ } catch (error) {
18
+ return null;
19
+ }
20
+ };
21
+
22
+ export const generateApiKey = () => {
23
+ return `sk_${Math.random().toString(36).substr(2, 48)}`;
24
+ };
package/test.js ADDED
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+
3
+ const BASE_URL = 'http://localhost:3000';
4
+
5
+ async function test() {
6
+ try {
7
+ console.log('๐Ÿงช Testing API Keys Creator System\n');
8
+
9
+ // Test 1: Health check
10
+ console.log('1. Testing health check...');
11
+ let res = await fetch(`${BASE_URL}/`);
12
+ let data = await res.json();
13
+ console.log(` โœ“ ${data.message}\n`);
14
+
15
+ // Test 2: Register
16
+ console.log('2. Testing registration...');
17
+ res = await fetch(`${BASE_URL}/auth/register`, {
18
+ method: 'POST',
19
+ headers: { 'Content-Type': 'application/json' },
20
+ body: JSON.stringify({
21
+ email: 'test@example.com',
22
+ password: 'testpass123'
23
+ })
24
+ });
25
+ data = await res.json();
26
+ if (!res.ok) {
27
+ console.log(` โœ“ Registration (second attempt) - ${data.error}\n`);
28
+ } else {
29
+ console.log(` โœ“ User registered: ${data.user.email}`);
30
+ console.log(` โœ“ Token: ${data.token.substring(0, 30)}...\n`);
31
+ }
32
+
33
+ // Test 3: Login
34
+ console.log('3. Testing login...');
35
+ res = await fetch(`${BASE_URL}/auth/login`, {
36
+ method: 'POST',
37
+ headers: { 'Content-Type': 'application/json' },
38
+ body: JSON.stringify({
39
+ email: 'test@example.com',
40
+ password: 'testpass123'
41
+ })
42
+ });
43
+ data = await res.json();
44
+ const token = data.token;
45
+ console.log(` โœ“ Login successful`);
46
+ console.log(` โœ“ Token: ${token.substring(0, 30)}...\n`);
47
+
48
+ // Test 4: Create API Key
49
+ console.log('4. Testing API key creation...');
50
+ res = await fetch(`${BASE_URL}/api/keys`, {
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ 'Authorization': `Bearer ${token}`
55
+ },
56
+ body: JSON.stringify({ name: 'Test Key' })
57
+ });
58
+ data = await res.json();
59
+ const keyId = data.key.id;
60
+ console.log(` โœ“ API Key created: ${data.key.name}`);
61
+ console.log(` โœ“ Key: ${data.key.key}\n`);
62
+
63
+ // Test 5: List API Keys
64
+ console.log('5. Testing list API keys...');
65
+ res = await fetch(`${BASE_URL}/api/keys`, {
66
+ headers: { 'Authorization': `Bearer ${token}` }
67
+ });
68
+ data = await res.json();
69
+ console.log(` โœ“ Found ${data.count} key(s)\n`);
70
+
71
+ // Test 6: Get single key
72
+ console.log('6. Testing get single key...');
73
+ res = await fetch(`${BASE_URL}/api/keys/${keyId}`, {
74
+ headers: { 'Authorization': `Bearer ${token}` }
75
+ });
76
+ data = await res.json();
77
+ console.log(` โœ“ Retrieved: ${data.key.name}\n`);
78
+
79
+ // Test 7: Update key
80
+ console.log('7. Testing update key...');
81
+ res = await fetch(`${BASE_URL}/api/keys/${keyId}`, {
82
+ method: 'PUT',
83
+ headers: {
84
+ 'Content-Type': 'application/json',
85
+ 'Authorization': `Bearer ${token}`
86
+ },
87
+ body: JSON.stringify({ name: 'Updated Test Key', active: false })
88
+ });
89
+ data = await res.json();
90
+ console.log(` โœ“ Updated: ${data.key.name} (active: ${data.key.active})\n`);
91
+
92
+ // Test 8: Record usage
93
+ console.log('8. Testing record usage...');
94
+ res = await fetch(`${BASE_URL}/api/keys/${keyId}/usage`, {
95
+ method: 'POST',
96
+ headers: { 'Authorization': `Bearer ${token}` }
97
+ });
98
+ data = await res.json();
99
+ console.log(` โœ“ ${data.message}\n`);
100
+
101
+ // Test 9: Delete key
102
+ console.log('9. Testing delete key...');
103
+ res = await fetch(`${BASE_URL}/api/keys/${keyId}`, {
104
+ method: 'DELETE',
105
+ headers: { 'Authorization': `Bearer ${token}` }
106
+ });
107
+ data = await res.json();
108
+ console.log(` โœ“ ${data.message}\n`);
109
+
110
+ console.log('โœ… All tests passed!');
111
+ process.exit(0);
112
+ } catch (error) {
113
+ console.error('โŒ Test failed:', error.message);
114
+ process.exit(1);
115
+ }
116
+ }
117
+
118
+ test();