@entergreat/pg-light 1.0.0 → 1.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/package.json +6 -32
- package/example-knex.js +0 -246
- package/example-model.js +0 -103
- package/example.js +0 -38
package/package.json
CHANGED
|
@@ -1,48 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@entergreat/pg-light",
|
|
3
3
|
"description": "Lightweight PostgreSQL client with Mongoose-like models. One-line connection, friendly CRUD API, and raw SQL support.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
},
|
|
7
|
+
"files": ["src/"],
|
|
8
|
+
"publishConfig": { "access": "restricted" },
|
|
10
9
|
"repository": {
|
|
11
10
|
"type": "git",
|
|
12
|
-
"url": "
|
|
11
|
+
"url": "https://github.com/entergreat/pg-light.git"
|
|
13
12
|
},
|
|
14
|
-
"keywords": [
|
|
15
|
-
"postgresql",
|
|
16
|
-
"postgres",
|
|
17
|
-
"pg",
|
|
18
|
-
"database",
|
|
19
|
-
"connection",
|
|
20
|
-
"pool",
|
|
21
|
-
"lightweight",
|
|
22
|
-
"simple",
|
|
23
|
-
"one-liner",
|
|
24
|
-
"sql",
|
|
25
|
-
"query",
|
|
26
|
-
"node",
|
|
27
|
-
"nodejs",
|
|
28
|
-
"model",
|
|
29
|
-
"mongoose",
|
|
30
|
-
"orm",
|
|
31
|
-
"crud",
|
|
32
|
-
"activerecord"
|
|
33
|
-
],
|
|
13
|
+
"keywords": ["postgresql", "postgres", "pg", "database", "orm", "crud", "lightweight", "entergreat"],
|
|
34
14
|
"author": "EnterGreat",
|
|
35
15
|
"license": "ISC",
|
|
36
|
-
"
|
|
37
|
-
"url": "https://github.com/nivkman/pg-light/issues"
|
|
38
|
-
},
|
|
39
|
-
"homepage": "https://github.com/nivkman/pg-light#readme",
|
|
16
|
+
"engines": { "node": ">=18.0.0" },
|
|
40
17
|
"dependencies": {
|
|
41
18
|
"pg": "^8.11.3",
|
|
42
19
|
"knex": "^3.1.0",
|
|
43
20
|
"logger-standard": "^2.0.0"
|
|
44
|
-
},
|
|
45
|
-
"engines": {
|
|
46
|
-
"node": ">=18.0.0"
|
|
47
21
|
}
|
|
48
22
|
}
|
package/example-knex.js
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import { connectDB } from './src/index.js';
|
|
2
|
-
|
|
3
|
-
// Example: Using Knex Query Builder for Complex Queries
|
|
4
|
-
|
|
5
|
-
async function main() {
|
|
6
|
-
// Connect to database
|
|
7
|
-
const db = await connectDB('postgresql://user:password@localhost:5432/mydb', {
|
|
8
|
-
service: 'knex-example',
|
|
9
|
-
logLevel: 'debug'
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
// SIMPLE QUERIES WITH KNEX
|
|
14
|
-
|
|
15
|
-
// Select all users
|
|
16
|
-
const allUsers = await db.builder('users').select('*');
|
|
17
|
-
console.log('All users:', allUsers);
|
|
18
|
-
|
|
19
|
-
// Select with WHERE
|
|
20
|
-
const activeUsers = await db.builder('users')
|
|
21
|
-
.select('*')
|
|
22
|
-
.where({ active: true })
|
|
23
|
-
.orderBy('created_at', 'desc');
|
|
24
|
-
console.log('Active users:', activeUsers);
|
|
25
|
-
|
|
26
|
-
// Select specific columns
|
|
27
|
-
const userEmails = await db.builder('users')
|
|
28
|
-
.select('id', 'name', 'email')
|
|
29
|
-
.where('age', '>', 25)
|
|
30
|
-
.limit(10);
|
|
31
|
-
console.log('User emails:', userEmails);
|
|
32
|
-
|
|
33
|
-
// COMPLEX QUERIES
|
|
34
|
-
|
|
35
|
-
// JOIN queries
|
|
36
|
-
const postsWithAuthors = await db.builder('posts')
|
|
37
|
-
.select('posts.*', 'users.name as author_name', 'users.email as author_email')
|
|
38
|
-
.join('users', 'posts.user_id', 'users.id')
|
|
39
|
-
.where('posts.published', true)
|
|
40
|
-
.orderBy('posts.created_at', 'desc')
|
|
41
|
-
.limit(20);
|
|
42
|
-
console.log('Posts with authors:', postsWithAuthors);
|
|
43
|
-
|
|
44
|
-
// Multiple JOINs
|
|
45
|
-
const postsWithCommentsCount = await db.builder('posts')
|
|
46
|
-
.select('posts.*', 'users.name as author')
|
|
47
|
-
.count('comments.id as comment_count')
|
|
48
|
-
.leftJoin('users', 'posts.user_id', 'users.id')
|
|
49
|
-
.leftJoin('comments', 'posts.id', 'comments.post_id')
|
|
50
|
-
.groupBy('posts.id', 'users.name')
|
|
51
|
-
.having(db.knex.raw('COUNT(comments.id) > ?', [5]))
|
|
52
|
-
.orderBy('comment_count', 'desc');
|
|
53
|
-
console.log('Popular posts:', postsWithCommentsCount);
|
|
54
|
-
|
|
55
|
-
// WHERE with multiple conditions
|
|
56
|
-
const filteredUsers = await db.builder('users')
|
|
57
|
-
.select('*')
|
|
58
|
-
.where('active', true)
|
|
59
|
-
.andWhere('age', '>=', 18)
|
|
60
|
-
.andWhere('age', '<=', 65)
|
|
61
|
-
.whereIn('role', ['admin', 'moderator'])
|
|
62
|
-
.whereNotNull('email')
|
|
63
|
-
.orderBy('created_at', 'desc');
|
|
64
|
-
console.log('Filtered users:', filteredUsers);
|
|
65
|
-
|
|
66
|
-
// OR conditions
|
|
67
|
-
const searchResults = await db.builder('users')
|
|
68
|
-
.select('*')
|
|
69
|
-
.where('name', 'like', '%John%')
|
|
70
|
-
.orWhere('email', 'like', '%john%')
|
|
71
|
-
.limit(10);
|
|
72
|
-
console.log('Search results:', searchResults);
|
|
73
|
-
|
|
74
|
-
// Subqueries
|
|
75
|
-
const usersWithManyPosts = await db.builder('users')
|
|
76
|
-
.select('users.*')
|
|
77
|
-
.whereIn('users.id', function() {
|
|
78
|
-
this.select('user_id')
|
|
79
|
-
.from('posts')
|
|
80
|
-
.groupBy('user_id')
|
|
81
|
-
.havingRaw('COUNT(*) > ?', [10]);
|
|
82
|
-
});
|
|
83
|
-
console.log('Prolific authors:', usersWithManyPosts);
|
|
84
|
-
|
|
85
|
-
// AGGREGATIONS
|
|
86
|
-
|
|
87
|
-
// Count
|
|
88
|
-
const userCount = await db.builder('users').count('* as total');
|
|
89
|
-
console.log('Total users:', userCount[0].total);
|
|
90
|
-
|
|
91
|
-
// Average, Sum, Min, Max
|
|
92
|
-
const stats = await db.builder('orders')
|
|
93
|
-
.select(
|
|
94
|
-
db.knex.raw('AVG(total) as avg_order'),
|
|
95
|
-
db.knex.raw('SUM(total) as revenue'),
|
|
96
|
-
db.knex.raw('MIN(total) as min_order'),
|
|
97
|
-
db.knex.raw('MAX(total) as max_order')
|
|
98
|
-
)
|
|
99
|
-
.where('status', 'completed');
|
|
100
|
-
console.log('Order stats:', stats[0]);
|
|
101
|
-
|
|
102
|
-
// Group by with aggregation
|
|
103
|
-
const ordersByUser = await db.builder('orders')
|
|
104
|
-
.select('user_id')
|
|
105
|
-
.count('* as order_count')
|
|
106
|
-
.sum('total as total_spent')
|
|
107
|
-
.groupBy('user_id')
|
|
108
|
-
.orderBy('total_spent', 'desc')
|
|
109
|
-
.limit(10);
|
|
110
|
-
console.log('Top spenders:', ordersByUser);
|
|
111
|
-
|
|
112
|
-
// INSERT
|
|
113
|
-
|
|
114
|
-
const [newUser] = await db.builder('users')
|
|
115
|
-
.insert({
|
|
116
|
-
name: 'Alice Johnson',
|
|
117
|
-
email: 'alice@example.com',
|
|
118
|
-
age: 28,
|
|
119
|
-
active: true
|
|
120
|
-
})
|
|
121
|
-
.returning('*');
|
|
122
|
-
console.log('Created user:', newUser);
|
|
123
|
-
|
|
124
|
-
// Bulk insert
|
|
125
|
-
const newUsers = await db.builder('users')
|
|
126
|
-
.insert([
|
|
127
|
-
{ name: 'Bob', email: 'bob@example.com', age: 30 },
|
|
128
|
-
{ name: 'Charlie', email: 'charlie@example.com', age: 25 }
|
|
129
|
-
])
|
|
130
|
-
.returning('*');
|
|
131
|
-
console.log('Created users:', newUsers);
|
|
132
|
-
|
|
133
|
-
// UPDATE
|
|
134
|
-
|
|
135
|
-
const updatedCount = await db.builder('users')
|
|
136
|
-
.where({ email: 'alice@example.com' })
|
|
137
|
-
.update({
|
|
138
|
-
last_login: db.knex.fn.now(),
|
|
139
|
-
login_count: db.knex.raw('login_count + 1')
|
|
140
|
-
});
|
|
141
|
-
console.log('Updated rows:', updatedCount);
|
|
142
|
-
|
|
143
|
-
// UPDATE with JOIN (PostgreSQL specific)
|
|
144
|
-
await db.knex.raw(`
|
|
145
|
-
UPDATE posts
|
|
146
|
-
SET featured = true
|
|
147
|
-
FROM users
|
|
148
|
-
WHERE posts.user_id = users.id
|
|
149
|
-
AND users.role = 'premium'
|
|
150
|
-
`);
|
|
151
|
-
|
|
152
|
-
// DELETE
|
|
153
|
-
|
|
154
|
-
const deletedCount = await db.builder('users')
|
|
155
|
-
.where('active', false)
|
|
156
|
-
.andWhere('last_login', '<', db.knex.raw("NOW() - INTERVAL '1 year'"))
|
|
157
|
-
.delete();
|
|
158
|
-
console.log('Deleted inactive users:', deletedCount);
|
|
159
|
-
|
|
160
|
-
// TRANSACTIONS WITH KNEX
|
|
161
|
-
|
|
162
|
-
await db.knex.transaction(async (trx) => {
|
|
163
|
-
// Insert user
|
|
164
|
-
const [user] = await trx('users')
|
|
165
|
-
.insert({ name: 'David', email: 'david@example.com' })
|
|
166
|
-
.returning('*');
|
|
167
|
-
|
|
168
|
-
// Insert posts for user
|
|
169
|
-
await trx('posts').insert([
|
|
170
|
-
{ user_id: user.id, title: 'Post 1', content: 'Content 1' },
|
|
171
|
-
{ user_id: user.id, title: 'Post 2', content: 'Content 2' }
|
|
172
|
-
]);
|
|
173
|
-
|
|
174
|
-
// Update user stats
|
|
175
|
-
await trx('users')
|
|
176
|
-
.where({ id: user.id })
|
|
177
|
-
.update({ post_count: 2 });
|
|
178
|
-
|
|
179
|
-
console.log('Transaction completed');
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
// RAW QUERIES WITH KNEX
|
|
183
|
-
|
|
184
|
-
const customQuery = await db.knex.raw(`
|
|
185
|
-
SELECT u.*, COUNT(p.id) as post_count
|
|
186
|
-
FROM users u
|
|
187
|
-
LEFT JOIN posts p ON u.id = p.user_id
|
|
188
|
-
WHERE u.active = ?
|
|
189
|
-
GROUP BY u.id
|
|
190
|
-
HAVING COUNT(p.id) > ?
|
|
191
|
-
ORDER BY post_count DESC
|
|
192
|
-
LIMIT ?
|
|
193
|
-
`, [true, 5, 10]);
|
|
194
|
-
console.log('Custom query results:', customQuery.rows);
|
|
195
|
-
|
|
196
|
-
// COMBINING MODEL API WITH KNEX
|
|
197
|
-
|
|
198
|
-
const User = db.model('users');
|
|
199
|
-
|
|
200
|
-
// Simple CRUD with Model
|
|
201
|
-
const simpleUser = await User.findById(1);
|
|
202
|
-
console.log('Simple find:', simpleUser);
|
|
203
|
-
|
|
204
|
-
// Complex query with Knex
|
|
205
|
-
const complexQuery = await db.builder('users')
|
|
206
|
-
.select('users.*', db.knex.raw('COUNT(posts.id) as post_count'))
|
|
207
|
-
.leftJoin('posts', 'users.id', 'posts.user_id')
|
|
208
|
-
.where('users.active', true)
|
|
209
|
-
.groupBy('users.id')
|
|
210
|
-
.having(db.knex.raw('COUNT(posts.id) > ?'), 10)
|
|
211
|
-
.orderBy('post_count', 'desc');
|
|
212
|
-
console.log('Complex query:', complexQuery);
|
|
213
|
-
|
|
214
|
-
// PAGINATION
|
|
215
|
-
|
|
216
|
-
const page = 2;
|
|
217
|
-
const perPage = 10;
|
|
218
|
-
const offset = (page - 1) * perPage;
|
|
219
|
-
|
|
220
|
-
const paginatedResults = await db.builder('users')
|
|
221
|
-
.select('*')
|
|
222
|
-
.where({ active: true })
|
|
223
|
-
.orderBy('created_at', 'desc')
|
|
224
|
-
.limit(perPage)
|
|
225
|
-
.offset(offset);
|
|
226
|
-
|
|
227
|
-
const [{ total }] = await db.builder('users')
|
|
228
|
-
.count('* as total')
|
|
229
|
-
.where({ active: true });
|
|
230
|
-
|
|
231
|
-
console.log({
|
|
232
|
-
data: paginatedResults,
|
|
233
|
-
page,
|
|
234
|
-
perPage,
|
|
235
|
-
total,
|
|
236
|
-
totalPages: Math.ceil(total / perPage)
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
} catch (error) {
|
|
240
|
-
console.error('Error:', error.message);
|
|
241
|
-
} finally {
|
|
242
|
-
await db.disconnect();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
main();
|
package/example-model.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { connectDB } from './src/index.js';
|
|
2
|
-
|
|
3
|
-
// Example: Mongoose-like Model API for pg-light
|
|
4
|
-
|
|
5
|
-
async function main() {
|
|
6
|
-
// Connect to database
|
|
7
|
-
const db = await connectDB('postgresql://user:password@localhost:5432/mydb', {
|
|
8
|
-
service: 'model-example',
|
|
9
|
-
logLevel: 'debug'
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
// Create models (like Mongoose)
|
|
13
|
-
const User = db.model('users');
|
|
14
|
-
const Post = db.model('posts');
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
// CREATE - Insert new records
|
|
18
|
-
const newUser = await User.create({
|
|
19
|
-
name: 'John Doe',
|
|
20
|
-
email: 'john@example.com',
|
|
21
|
-
age: 30
|
|
22
|
-
});
|
|
23
|
-
console.log('Created user:', newUser);
|
|
24
|
-
|
|
25
|
-
// FIND ALL - Get all records
|
|
26
|
-
const allUsers = await User.find();
|
|
27
|
-
console.log('All users:', allUsers);
|
|
28
|
-
|
|
29
|
-
// FIND WITH CONDITIONS - Filter records
|
|
30
|
-
const activeUsers = await User.find({ active: true });
|
|
31
|
-
console.log('Active users:', activeUsers);
|
|
32
|
-
|
|
33
|
-
// FIND WITH OPTIONS - Pagination
|
|
34
|
-
const firstTenUsers = await User.find({}, { limit: 10, offset: 0 });
|
|
35
|
-
console.log('First 10 users:', firstTenUsers);
|
|
36
|
-
|
|
37
|
-
// FIND ONE - Get single record
|
|
38
|
-
const john = await User.findOne({ email: 'john@example.com' });
|
|
39
|
-
console.log('Found John:', john);
|
|
40
|
-
|
|
41
|
-
// FIND BY ID - Get by primary key
|
|
42
|
-
const userById = await User.findById(1);
|
|
43
|
-
console.log('User #1:', userById);
|
|
44
|
-
|
|
45
|
-
// UPDATE - Update records
|
|
46
|
-
const updatedUsers = await User.update(
|
|
47
|
-
{ email: 'john@example.com' },
|
|
48
|
-
{ last_login: new Date() }
|
|
49
|
-
);
|
|
50
|
-
console.log('Updated users:', updatedUsers);
|
|
51
|
-
|
|
52
|
-
// UPDATE BY ID - Update single record
|
|
53
|
-
const updatedUser = await User.updateById(1, { name: 'John Smith' });
|
|
54
|
-
console.log('Updated user:', updatedUser);
|
|
55
|
-
|
|
56
|
-
// COUNT - Count records
|
|
57
|
-
const totalUsers = await User.count();
|
|
58
|
-
console.log('Total users:', totalUsers);
|
|
59
|
-
|
|
60
|
-
const activeCount = await User.count({ active: true });
|
|
61
|
-
console.log('Active users count:', activeCount);
|
|
62
|
-
|
|
63
|
-
// DELETE - Remove records
|
|
64
|
-
const deletedUsers = await User.delete({ active: false });
|
|
65
|
-
console.log('Deleted inactive users:', deletedUsers);
|
|
66
|
-
|
|
67
|
-
// DELETE BY ID - Remove single record
|
|
68
|
-
const deletedUser = await User.deleteById(999);
|
|
69
|
-
console.log('Deleted user:', deletedUser);
|
|
70
|
-
|
|
71
|
-
// RELATIONSHIPS - Create related records
|
|
72
|
-
const post = await Post.create({
|
|
73
|
-
title: 'My First Post',
|
|
74
|
-
content: 'Hello World!',
|
|
75
|
-
user_id: newUser.id,
|
|
76
|
-
published: true
|
|
77
|
-
});
|
|
78
|
-
console.log('Created post:', post);
|
|
79
|
-
|
|
80
|
-
// Find posts by user
|
|
81
|
-
const userPosts = await Post.find({ user_id: newUser.id });
|
|
82
|
-
console.log('User posts:', userPosts);
|
|
83
|
-
|
|
84
|
-
// COMPLEX QUERIES - Still use raw SQL when needed
|
|
85
|
-
const popularPosts = await db.query(
|
|
86
|
-
`SELECT p.*, u.name as author_name
|
|
87
|
-
FROM posts p
|
|
88
|
-
JOIN users u ON p.user_id = u.id
|
|
89
|
-
WHERE p.views > $1
|
|
90
|
-
ORDER BY p.views DESC
|
|
91
|
-
LIMIT $2`,
|
|
92
|
-
[1000, 10]
|
|
93
|
-
);
|
|
94
|
-
console.log('Popular posts:', popularPosts.rows);
|
|
95
|
-
|
|
96
|
-
} catch (error) {
|
|
97
|
-
console.error('Error:', error.message);
|
|
98
|
-
} finally {
|
|
99
|
-
await db.disconnect();
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
main();
|
package/example.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { connectDB } from './src/index.js';
|
|
2
|
-
|
|
3
|
-
// Example usage of pg-light
|
|
4
|
-
|
|
5
|
-
async function main() {
|
|
6
|
-
// Connect to database (use your connection string)
|
|
7
|
-
const db = await connectDB('postgresql://user:password@localhost:5432/mydb', {
|
|
8
|
-
service: 'pg-light-example',
|
|
9
|
-
logLevel: 'debug'
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
try {
|
|
13
|
-
// Simple query
|
|
14
|
-
const result = await db.query('SELECT NOW() as current_time');
|
|
15
|
-
console.log('Current time:', result.rows[0].current_time);
|
|
16
|
-
|
|
17
|
-
// Parameterized query
|
|
18
|
-
const users = await db.query(
|
|
19
|
-
'SELECT * FROM users WHERE active = $1 LIMIT $2',
|
|
20
|
-
[true, 10]
|
|
21
|
-
);
|
|
22
|
-
console.log('Active users:', users.rows);
|
|
23
|
-
|
|
24
|
-
// Transaction example
|
|
25
|
-
await db.transaction(async (client) => {
|
|
26
|
-
await client.query('INSERT INTO logs (message) VALUES ($1)', ['Transaction started']);
|
|
27
|
-
await client.query('INSERT INTO logs (message) VALUES ($1)', ['Transaction completed']);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
} catch (error) {
|
|
31
|
-
console.error('Error:', error.message);
|
|
32
|
-
} finally {
|
|
33
|
-
// Always disconnect
|
|
34
|
-
await db.disconnect();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
main();
|