@jgamaraalv/ts-dev-kit 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/.claude-plugin/marketplace.json +24 -0
- package/.claude-plugin/plugin.json +24 -0
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +128 -0
- package/agents/accessibility-pro.md +139 -0
- package/agents/api-builder.md +110 -0
- package/agents/code-reviewer.md +190 -0
- package/agents/database-expert.md +138 -0
- package/agents/debugger.md +241 -0
- package/agents/docker-expert.md +51 -0
- package/agents/multi-agent-coordinator.md +378 -0
- package/agents/nextjs-expert.md +136 -0
- package/agents/performance-engineer.md +138 -0
- package/agents/playwright-expert.md +126 -0
- package/agents/react-specialist.md +97 -0
- package/agents/security-scanner.md +105 -0
- package/agents/test-generator.md +221 -0
- package/agents/typescript-pro.md +253 -0
- package/agents/ux-optimizer.md +93 -0
- package/docs/rules/orchestration.md.template +126 -0
- package/package.json +28 -0
- package/skills/bullmq/SKILL.md +225 -0
- package/skills/bullmq/references/flows-and-schedulers.md +186 -0
- package/skills/bullmq/references/job-types-and-options.md +163 -0
- package/skills/bullmq/references/patterns.md +273 -0
- package/skills/bullmq/references/production.md +308 -0
- package/skills/composition-patterns/SKILL.md +58 -0
- package/skills/composition-patterns/references/architecture-avoid-boolean-props.md +87 -0
- package/skills/composition-patterns/references/architecture-compound-components.md +107 -0
- package/skills/composition-patterns/references/patterns-children-over-render-props.md +77 -0
- package/skills/composition-patterns/references/patterns-explicit-variants.md +87 -0
- package/skills/composition-patterns/references/react19-no-forwardref.md +37 -0
- package/skills/composition-patterns/references/state-context-interface.md +194 -0
- package/skills/composition-patterns/references/state-decouple-implementation.md +96 -0
- package/skills/composition-patterns/references/state-lift-state.md +126 -0
- package/skills/conventional-commits/SKILL.md +148 -0
- package/skills/docker/SKILL.md +55 -0
- package/skills/docker/references/compose-configs.md +95 -0
- package/skills/docker/references/monorepo-dockerfile.md +111 -0
- package/skills/drizzle-pg/SKILL.md +202 -0
- package/skills/drizzle-pg/references/advanced.md +299 -0
- package/skills/drizzle-pg/references/migrations.md +214 -0
- package/skills/drizzle-pg/references/queries.md +321 -0
- package/skills/drizzle-pg/references/relations.md +272 -0
- package/skills/drizzle-pg/references/schema-pg.md +256 -0
- package/skills/drizzle-pg/references/sql-operator.md +215 -0
- package/skills/fastify-best-practices/SKILL.md +143 -0
- package/skills/fastify-best-practices/references/hooks-and-lifecycle.md +122 -0
- package/skills/fastify-best-practices/references/plugins-and-encapsulation.md +137 -0
- package/skills/fastify-best-practices/references/request-reply-errors.md +189 -0
- package/skills/fastify-best-practices/references/routes-and-handlers.md +134 -0
- package/skills/fastify-best-practices/references/server-and-options.md +127 -0
- package/skills/fastify-best-practices/references/typescript-and-logging.md +223 -0
- package/skills/fastify-best-practices/references/validation-and-serialization.md +190 -0
- package/skills/ioredis/SKILL.md +51 -0
- package/skills/ioredis/references/advanced-patterns.md +312 -0
- package/skills/ioredis/references/cluster-sentinel.md +280 -0
- package/skills/ioredis/references/connection-options.md +187 -0
- package/skills/ioredis/references/core-api.md +179 -0
- package/skills/nextjs-best-practices/SKILL.md +194 -0
- package/skills/nextjs-best-practices/references/async-patterns.md +84 -0
- package/skills/nextjs-best-practices/references/bundling.md +192 -0
- package/skills/nextjs-best-practices/references/data-patterns.md +310 -0
- package/skills/nextjs-best-practices/references/debug-tricks.md +127 -0
- package/skills/nextjs-best-practices/references/directives.md +74 -0
- package/skills/nextjs-best-practices/references/error-handling.md +237 -0
- package/skills/nextjs-best-practices/references/file-conventions.md +152 -0
- package/skills/nextjs-best-practices/references/font.md +175 -0
- package/skills/nextjs-best-practices/references/functions.md +116 -0
- package/skills/nextjs-best-practices/references/hydration-error.md +86 -0
- package/skills/nextjs-best-practices/references/image.md +184 -0
- package/skills/nextjs-best-practices/references/metadata.md +305 -0
- package/skills/nextjs-best-practices/references/parallel-routes.md +299 -0
- package/skills/nextjs-best-practices/references/route-handlers.md +154 -0
- package/skills/nextjs-best-practices/references/rsc-boundaries.md +168 -0
- package/skills/nextjs-best-practices/references/runtime-selection.md +40 -0
- package/skills/nextjs-best-practices/references/scripts.md +148 -0
- package/skills/nextjs-best-practices/references/self-hosting.md +210 -0
- package/skills/nextjs-best-practices/references/suspense-boundaries.md +67 -0
- package/skills/owasp-security-review/SKILL.md +98 -0
- package/skills/owasp-security-review/references/a01-broken-access-control.md +78 -0
- package/skills/owasp-security-review/references/a02-security-misconfiguration.md +81 -0
- package/skills/owasp-security-review/references/a03-supply-chain-failures.md +65 -0
- package/skills/owasp-security-review/references/a04-cryptographic-failures.md +82 -0
- package/skills/owasp-security-review/references/a05-injection.md +106 -0
- package/skills/owasp-security-review/references/a06-insecure-design.md +76 -0
- package/skills/owasp-security-review/references/a07-authentication-failures.md +83 -0
- package/skills/owasp-security-review/references/a08-integrity-failures.md +72 -0
- package/skills/owasp-security-review/references/a09-logging-alerting-failures.md +76 -0
- package/skills/owasp-security-review/references/a10-exceptional-conditions.md +131 -0
- package/skills/postgresql/SKILL.md +50 -0
- package/skills/postgresql/references/ddl-schema.md +300 -0
- package/skills/postgresql/references/indexes.md +257 -0
- package/skills/postgresql/references/jsonb.md +261 -0
- package/skills/postgresql/references/performance.md +291 -0
- package/skills/postgresql/references/psql-cli.md +153 -0
- package/skills/postgresql/references/queries.md +287 -0
- package/skills/postgresql/references/transactions.md +280 -0
- package/skills/react-best-practices/SKILL.md +110 -0
- package/skills/react-best-practices/references/advanced-patterns.md +91 -0
- package/skills/react-best-practices/references/async-patterns.md +233 -0
- package/skills/react-best-practices/references/bundle-optimization.md +201 -0
- package/skills/react-best-practices/references/client-patterns.md +178 -0
- package/skills/react-best-practices/references/js-performance.md +210 -0
- package/skills/react-best-practices/references/rendering-performance.md +209 -0
- package/skills/react-best-practices/references/rerender-optimization.md +316 -0
- package/skills/react-best-practices/references/server-performance.md +274 -0
- package/skills/service-worker/SKILL.md +195 -0
- package/skills/service-worker/references/api-reference.md +114 -0
- package/skills/service-worker/references/caching-strategies.md +202 -0
- package/skills/service-worker/references/push-and-sync.md +261 -0
- package/skills/typescript-conventions/SKILL.md +51 -0
- package/skills/ui-ux-guidelines/SKILL.md +105 -0
- package/skills/ui-ux-guidelines/references/accessibility-and-interaction.md +74 -0
- package/skills/ui-ux-guidelines/references/forms-content-checklist.md +126 -0
- package/skills/ui-ux-guidelines/references/layout-typography-animation.md +95 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# PostgreSQL Queries Reference
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
1. [SELECT anatomy](#select-anatomy)
|
|
6
|
+
2. [JOINs](#joins)
|
|
7
|
+
3. [Subqueries](#subqueries)
|
|
8
|
+
4. [CTEs (WITH clauses)](#ctes)
|
|
9
|
+
5. [Window functions](#window-functions)
|
|
10
|
+
6. [Aggregation](#aggregation)
|
|
11
|
+
7. [Set operations](#set-operations)
|
|
12
|
+
8. [INSERT / UPDATE / DELETE / UPSERT](#dml)
|
|
13
|
+
9. [LATERAL joins](#lateral)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## SELECT anatomy
|
|
18
|
+
|
|
19
|
+
```sql
|
|
20
|
+
SELECT [DISTINCT] expression [AS alias], ...
|
|
21
|
+
FROM table [AS alias]
|
|
22
|
+
[JOIN ...]
|
|
23
|
+
[WHERE condition]
|
|
24
|
+
[GROUP BY expression, ...]
|
|
25
|
+
[HAVING condition]
|
|
26
|
+
[WINDOW w AS (window_def)]
|
|
27
|
+
[ORDER BY expression [ASC|DESC] [NULLS FIRST|LAST]]
|
|
28
|
+
[LIMIT n] [OFFSET n]
|
|
29
|
+
[FOR UPDATE | FOR SHARE]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Execution order (logical): FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT/OFFSET.
|
|
33
|
+
|
|
34
|
+
```sql
|
|
35
|
+
-- DISTINCT ON — keep first row per group (PostgreSQL extension)
|
|
36
|
+
SELECT DISTINCT ON (department_id) department_id, name, salary
|
|
37
|
+
FROM employees
|
|
38
|
+
ORDER BY department_id, salary DESC;
|
|
39
|
+
|
|
40
|
+
-- Return row if exists, else nothing
|
|
41
|
+
SELECT * FROM users WHERE email = $1 FOR UPDATE;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## JOINs
|
|
47
|
+
|
|
48
|
+
```sql
|
|
49
|
+
-- INNER JOIN (default)
|
|
50
|
+
SELECT o.id, c.name FROM orders o JOIN customers c ON o.customer_id = c.id;
|
|
51
|
+
|
|
52
|
+
-- LEFT JOIN — all rows from left, NULL for unmatched right
|
|
53
|
+
SELECT c.name, COUNT(o.id) FROM customers c LEFT JOIN orders o ON o.customer_id = c.id GROUP BY c.id;
|
|
54
|
+
|
|
55
|
+
-- FULL OUTER JOIN
|
|
56
|
+
SELECT a.id, b.id FROM a FULL OUTER JOIN b ON a.key = b.key;
|
|
57
|
+
|
|
58
|
+
-- CROSS JOIN — cartesian product
|
|
59
|
+
SELECT * FROM sizes CROSS JOIN colors;
|
|
60
|
+
|
|
61
|
+
-- Self-join
|
|
62
|
+
SELECT e.name, m.name AS manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.id;
|
|
63
|
+
|
|
64
|
+
-- Multiple join conditions
|
|
65
|
+
SELECT * FROM a JOIN b ON a.x = b.x AND a.y > b.y;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Subqueries
|
|
71
|
+
|
|
72
|
+
```sql
|
|
73
|
+
-- In WHERE
|
|
74
|
+
SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE country = 'BR');
|
|
75
|
+
|
|
76
|
+
-- EXISTS (stops at first match — efficient)
|
|
77
|
+
SELECT * FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);
|
|
78
|
+
|
|
79
|
+
-- Correlated subquery in SELECT (runs once per row — can be slow)
|
|
80
|
+
SELECT name, (SELECT COUNT(*) FROM orders o WHERE o.customer_id = c.id) AS order_count
|
|
81
|
+
FROM customers c;
|
|
82
|
+
|
|
83
|
+
-- Scalar subquery
|
|
84
|
+
SELECT * FROM orders WHERE total > (SELECT AVG(total) FROM orders);
|
|
85
|
+
|
|
86
|
+
-- Derived table (subquery in FROM)
|
|
87
|
+
SELECT dept, avg_sal FROM (
|
|
88
|
+
SELECT department, AVG(salary) AS avg_sal FROM employees GROUP BY department
|
|
89
|
+
) AS dept_avg
|
|
90
|
+
WHERE avg_sal > 50000;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## CTEs
|
|
96
|
+
|
|
97
|
+
```sql
|
|
98
|
+
-- Basic CTE
|
|
99
|
+
WITH recent_orders AS (
|
|
100
|
+
SELECT * FROM orders WHERE created_at > NOW() - INTERVAL '7 days'
|
|
101
|
+
)
|
|
102
|
+
SELECT customer_id, COUNT(*) FROM recent_orders GROUP BY customer_id;
|
|
103
|
+
|
|
104
|
+
-- Multiple CTEs
|
|
105
|
+
WITH
|
|
106
|
+
a AS (SELECT ...),
|
|
107
|
+
b AS (SELECT ... FROM a)
|
|
108
|
+
SELECT * FROM b;
|
|
109
|
+
|
|
110
|
+
-- Writable CTE (INSERT/UPDATE/DELETE returning rows)
|
|
111
|
+
WITH deleted AS (
|
|
112
|
+
DELETE FROM sessions WHERE expires_at < NOW() RETURNING user_id
|
|
113
|
+
)
|
|
114
|
+
INSERT INTO audit_log (user_id, event) SELECT user_id, 'session_expired' FROM deleted;
|
|
115
|
+
|
|
116
|
+
-- Recursive CTE (e.g., tree traversal)
|
|
117
|
+
WITH RECURSIVE tree AS (
|
|
118
|
+
-- Base case
|
|
119
|
+
SELECT id, parent_id, name, 0 AS depth FROM categories WHERE parent_id IS NULL
|
|
120
|
+
UNION ALL
|
|
121
|
+
-- Recursive case
|
|
122
|
+
SELECT c.id, c.parent_id, c.name, t.depth + 1
|
|
123
|
+
FROM categories c JOIN tree t ON c.parent_id = t.id
|
|
124
|
+
)
|
|
125
|
+
SELECT * FROM tree ORDER BY depth, name;
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
CTE materialization: By default CTEs are optimization fences (materialized once). Add `NOT MATERIALIZED` to allow the planner to inline them:
|
|
129
|
+
|
|
130
|
+
```sql
|
|
131
|
+
WITH data AS NOT MATERIALIZED (SELECT * FROM big_table WHERE ...)
|
|
132
|
+
SELECT * FROM data WHERE extra_filter;
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Window functions
|
|
138
|
+
|
|
139
|
+
```sql
|
|
140
|
+
-- Syntax
|
|
141
|
+
function() OVER ([PARTITION BY col] [ORDER BY col] [frame_clause])
|
|
142
|
+
|
|
143
|
+
-- ROW_NUMBER, RANK, DENSE_RANK
|
|
144
|
+
SELECT name, salary,
|
|
145
|
+
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn,
|
|
146
|
+
RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rnk,
|
|
147
|
+
DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS drnk
|
|
148
|
+
FROM employees;
|
|
149
|
+
|
|
150
|
+
-- Running total
|
|
151
|
+
SELECT date, amount, SUM(amount) OVER (ORDER BY date) AS running_total FROM sales;
|
|
152
|
+
|
|
153
|
+
-- Moving average (last 7 rows)
|
|
154
|
+
SELECT date, amount,
|
|
155
|
+
AVG(amount) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS moving_avg
|
|
156
|
+
FROM sales;
|
|
157
|
+
|
|
158
|
+
-- LAG / LEAD — access adjacent rows
|
|
159
|
+
SELECT date, amount,
|
|
160
|
+
LAG(amount, 1) OVER (ORDER BY date) AS prev_day,
|
|
161
|
+
amount - LAG(amount, 1) OVER (ORDER BY date) AS delta
|
|
162
|
+
FROM sales;
|
|
163
|
+
|
|
164
|
+
-- FIRST_VALUE / LAST_VALUE
|
|
165
|
+
SELECT dept, name, salary,
|
|
166
|
+
FIRST_VALUE(name) OVER (PARTITION BY dept ORDER BY salary DESC) AS top_earner
|
|
167
|
+
FROM employees;
|
|
168
|
+
|
|
169
|
+
-- Named WINDOW clause (reuse)
|
|
170
|
+
SELECT name, salary,
|
|
171
|
+
RANK() OVER w,
|
|
172
|
+
DENSE_RANK() OVER w
|
|
173
|
+
FROM employees
|
|
174
|
+
WINDOW w AS (PARTITION BY dept ORDER BY salary DESC);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Frame clauses: `ROWS BETWEEN n PRECEDING AND CURRENT ROW`, `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`, `ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING`.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Aggregation
|
|
182
|
+
|
|
183
|
+
```sql
|
|
184
|
+
SELECT dept,
|
|
185
|
+
COUNT(*),
|
|
186
|
+
COUNT(DISTINCT manager_id),
|
|
187
|
+
SUM(salary),
|
|
188
|
+
AVG(salary),
|
|
189
|
+
MIN(salary), MAX(salary),
|
|
190
|
+
ARRAY_AGG(name ORDER BY salary DESC),
|
|
191
|
+
STRING_AGG(name, ', ' ORDER BY name),
|
|
192
|
+
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) AS median
|
|
193
|
+
FROM employees
|
|
194
|
+
WHERE active = true
|
|
195
|
+
GROUP BY dept
|
|
196
|
+
HAVING COUNT(*) > 5
|
|
197
|
+
ORDER BY AVG(salary) DESC;
|
|
198
|
+
|
|
199
|
+
-- FILTER clause (conditional aggregate)
|
|
200
|
+
SELECT
|
|
201
|
+
COUNT(*) FILTER (WHERE status = 'active') AS active_count,
|
|
202
|
+
COUNT(*) FILTER (WHERE status = 'inactive') AS inactive_count
|
|
203
|
+
FROM users;
|
|
204
|
+
|
|
205
|
+
-- GROUPING SETS / ROLLUP / CUBE
|
|
206
|
+
SELECT region, product, SUM(revenue)
|
|
207
|
+
FROM sales
|
|
208
|
+
GROUP BY ROLLUP (region, product); -- subtotals per region + grand total
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Set operations
|
|
214
|
+
|
|
215
|
+
```sql
|
|
216
|
+
UNION -- deduplicate
|
|
217
|
+
UNION ALL -- keep duplicates (faster)
|
|
218
|
+
INTERSECT -- rows in both
|
|
219
|
+
EXCEPT -- rows in first but not second
|
|
220
|
+
|
|
221
|
+
SELECT id FROM table_a
|
|
222
|
+
UNION ALL
|
|
223
|
+
SELECT id FROM table_b
|
|
224
|
+
ORDER BY id; -- ORDER BY applies to the combined result
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## DML
|
|
230
|
+
|
|
231
|
+
```sql
|
|
232
|
+
-- INSERT
|
|
233
|
+
INSERT INTO users (name, email, created_at)
|
|
234
|
+
VALUES ('Alice', 'alice@example.com', NOW())
|
|
235
|
+
RETURNING id, created_at;
|
|
236
|
+
|
|
237
|
+
-- INSERT multiple rows
|
|
238
|
+
INSERT INTO tags (name) VALUES ('dogs'), ('cats'), ('pets');
|
|
239
|
+
|
|
240
|
+
-- UPSERT (ON CONFLICT)
|
|
241
|
+
INSERT INTO user_prefs (user_id, key, value)
|
|
242
|
+
VALUES ($1, $2, $3)
|
|
243
|
+
ON CONFLICT (user_id, key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW();
|
|
244
|
+
|
|
245
|
+
-- ON CONFLICT DO NOTHING
|
|
246
|
+
INSERT INTO events (id, payload) VALUES ($1, $2) ON CONFLICT (id) DO NOTHING;
|
|
247
|
+
|
|
248
|
+
-- UPDATE
|
|
249
|
+
UPDATE orders
|
|
250
|
+
SET status = 'shipped', updated_at = NOW()
|
|
251
|
+
WHERE id = $1 AND status = 'processing'
|
|
252
|
+
RETURNING *;
|
|
253
|
+
|
|
254
|
+
-- UPDATE with JOIN (using FROM)
|
|
255
|
+
UPDATE employees e
|
|
256
|
+
SET salary = e.salary * 1.1
|
|
257
|
+
FROM departments d
|
|
258
|
+
WHERE e.dept_id = d.id AND d.name = 'Engineering';
|
|
259
|
+
|
|
260
|
+
-- DELETE
|
|
261
|
+
DELETE FROM sessions WHERE expires_at < NOW() RETURNING id;
|
|
262
|
+
|
|
263
|
+
-- TRUNCATE (faster than DELETE for full table, unlogged)
|
|
264
|
+
TRUNCATE TABLE audit_log RESTART IDENTITY CASCADE;
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## LATERAL
|
|
270
|
+
|
|
271
|
+
`LATERAL` allows a subquery in `FROM` to reference columns from preceding tables:
|
|
272
|
+
|
|
273
|
+
```sql
|
|
274
|
+
-- Get latest N orders per customer
|
|
275
|
+
SELECT c.name, o.*
|
|
276
|
+
FROM customers c,
|
|
277
|
+
LATERAL (
|
|
278
|
+
SELECT * FROM orders WHERE customer_id = c.id ORDER BY created_at DESC LIMIT 3
|
|
279
|
+
) o;
|
|
280
|
+
|
|
281
|
+
-- With LEFT JOIN LATERAL (include customers with no orders)
|
|
282
|
+
SELECT c.name, o.id
|
|
283
|
+
FROM customers c
|
|
284
|
+
LEFT JOIN LATERAL (
|
|
285
|
+
SELECT id FROM orders WHERE customer_id = c.id ORDER BY created_at DESC LIMIT 1
|
|
286
|
+
) o ON true;
|
|
287
|
+
```
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# PostgreSQL Transactions Reference
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
1. [Transaction basics](#basics)
|
|
6
|
+
2. [Savepoints](#savepoints)
|
|
7
|
+
3. [Isolation levels](#isolation-levels)
|
|
8
|
+
4. [Locking](#locking)
|
|
9
|
+
5. [Advisory locks](#advisory-locks)
|
|
10
|
+
6. [MVCC overview](#mvcc)
|
|
11
|
+
7. [Common patterns](#patterns)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Basics
|
|
16
|
+
|
|
17
|
+
Every SQL statement runs inside a transaction. Without `BEGIN`, each statement has an implicit `BEGIN` + `COMMIT`.
|
|
18
|
+
|
|
19
|
+
```sql
|
|
20
|
+
-- Explicit transaction block
|
|
21
|
+
BEGIN;
|
|
22
|
+
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
|
|
23
|
+
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
|
|
24
|
+
COMMIT;
|
|
25
|
+
|
|
26
|
+
-- Rollback on error
|
|
27
|
+
BEGIN;
|
|
28
|
+
DELETE FROM orders WHERE id = 42;
|
|
29
|
+
-- Discovered wrong order, cancel:
|
|
30
|
+
ROLLBACK;
|
|
31
|
+
|
|
32
|
+
-- Set isolation level (must be first statement after BEGIN)
|
|
33
|
+
BEGIN;
|
|
34
|
+
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
|
35
|
+
SELECT ...;
|
|
36
|
+
COMMIT;
|
|
37
|
+
|
|
38
|
+
-- Shorthand
|
|
39
|
+
BEGIN ISOLATION LEVEL REPEATABLE READ;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
DDL statements (`CREATE TABLE`, `ALTER TABLE`, `DROP`) are transactional in PostgreSQL — they can be rolled back.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Savepoints
|
|
47
|
+
|
|
48
|
+
Savepoints allow partial rollback within a transaction:
|
|
49
|
+
|
|
50
|
+
```sql
|
|
51
|
+
BEGIN;
|
|
52
|
+
INSERT INTO orders (customer_id, total) VALUES (1, 100) RETURNING id; -- id = 42
|
|
53
|
+
|
|
54
|
+
SAVEPOINT sp1;
|
|
55
|
+
|
|
56
|
+
INSERT INTO order_items (order_id, product_id, qty)
|
|
57
|
+
VALUES (42, 999, 1); -- product 999 doesn't exist → error
|
|
58
|
+
|
|
59
|
+
ROLLBACK TO SAVEPOINT sp1; -- undo order_items insert, keep orders insert
|
|
60
|
+
|
|
61
|
+
INSERT INTO order_items (order_id, product_id, qty)
|
|
62
|
+
VALUES (42, 1, 1); -- correct product
|
|
63
|
+
|
|
64
|
+
RELEASE SAVEPOINT sp1; -- optional cleanup
|
|
65
|
+
COMMIT;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
After `ROLLBACK TO SAVEPOINT`, the savepoint still exists and can be rolled back to again. Use `RELEASE SAVEPOINT` to free it.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Isolation levels
|
|
73
|
+
|
|
74
|
+
PostgreSQL supports four isolation levels. Default is **Read Committed**.
|
|
75
|
+
|
|
76
|
+
| Level | Dirty Read | Non-repeatable Read | Phantom Read | Serialization Anomaly |
|
|
77
|
+
| ---------------------------- | -------------- | ------------------- | ---------------- | --------------------- |
|
|
78
|
+
| Read Uncommitted | Not possible\* | Possible | Possible | Possible |
|
|
79
|
+
| **Read Committed** (default) | Not possible\* | **Possible** | **Possible** | **Possible** |
|
|
80
|
+
| Repeatable Read | Not possible | Not possible | Not possible\*\* | **Possible** |
|
|
81
|
+
| Serializable | Not possible | Not possible | Not possible | Not possible |
|
|
82
|
+
|
|
83
|
+
\* PostgreSQL never allows dirty reads even at Read Uncommitted.
|
|
84
|
+
\*\* PostgreSQL's Repeatable Read prevents phantoms using MVCC snapshots.
|
|
85
|
+
|
|
86
|
+
### Read Committed (default)
|
|
87
|
+
|
|
88
|
+
Each statement sees its own snapshot (data committed before the statement started). Safe for most OLTP. Vulnerable to "lost update" in read-modify-write patterns without locking.
|
|
89
|
+
|
|
90
|
+
```sql
|
|
91
|
+
-- Common pattern: SELECT FOR UPDATE to prevent lost update
|
|
92
|
+
BEGIN;
|
|
93
|
+
SELECT * FROM products WHERE id = $1 FOR UPDATE; -- lock the row
|
|
94
|
+
UPDATE products SET stock = stock - 1 WHERE id = $1;
|
|
95
|
+
COMMIT;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Repeatable Read
|
|
99
|
+
|
|
100
|
+
The entire transaction sees a single consistent snapshot (taken at first statement). Prevents non-repeatable reads and phantoms. May abort with:
|
|
101
|
+
`ERROR: could not serialize access due to concurrent update` — retry the transaction.
|
|
102
|
+
|
|
103
|
+
```sql
|
|
104
|
+
BEGIN ISOLATION LEVEL REPEATABLE READ;
|
|
105
|
+
SELECT SUM(balance) FROM accounts; -- snapshot taken here
|
|
106
|
+
-- Other transactions' commits won't affect our subsequent reads
|
|
107
|
+
COMMIT;
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Serializable
|
|
111
|
+
|
|
112
|
+
Strongest guarantee. Transactions execute as if run serially. Uses Serializable Snapshot Isolation (SSI). May abort with:
|
|
113
|
+
`ERROR: could not serialize access due to read/write dependencies among transactions` — must retry.
|
|
114
|
+
|
|
115
|
+
```sql
|
|
116
|
+
BEGIN ISOLATION LEVEL SERIALIZABLE;
|
|
117
|
+
-- Safe for concurrent write-skew prevention
|
|
118
|
+
COMMIT;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Locking
|
|
124
|
+
|
|
125
|
+
### Row-level locks
|
|
126
|
+
|
|
127
|
+
```sql
|
|
128
|
+
-- FOR UPDATE — exclusive lock; blocks other FOR UPDATE, FOR SHARE, UPDATE, DELETE
|
|
129
|
+
SELECT * FROM orders WHERE id = $1 FOR UPDATE;
|
|
130
|
+
|
|
131
|
+
-- FOR SHARE — shared lock; blocks FOR UPDATE but not other FOR SHARE
|
|
132
|
+
SELECT * FROM users WHERE id = $1 FOR SHARE;
|
|
133
|
+
|
|
134
|
+
-- SKIP LOCKED — skip rows currently locked (queue processing)
|
|
135
|
+
SELECT * FROM jobs WHERE status = 'pending' LIMIT 1 FOR UPDATE SKIP LOCKED;
|
|
136
|
+
|
|
137
|
+
-- NOWAIT — fail immediately if lock unavailable
|
|
138
|
+
SELECT * FROM orders WHERE id = $1 FOR UPDATE NOWAIT;
|
|
139
|
+
|
|
140
|
+
-- Lock specific tables (usually not needed)
|
|
141
|
+
LOCK TABLE orders IN EXCLUSIVE MODE;
|
|
142
|
+
LOCK TABLE orders IN ACCESS SHARE MODE; -- weakest, just prevents DROP TABLE
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Table-level lock modes (strongest to weakest)
|
|
146
|
+
|
|
147
|
+
| Mode | Blocks | When acquired |
|
|
148
|
+
| ------------------------ | ---------------------------------- | ------------------------------------------ |
|
|
149
|
+
| `ACCESS EXCLUSIVE` | Everything | ALTER TABLE, DROP TABLE, VACUUM FULL |
|
|
150
|
+
| `EXCLUSIVE` | All writes + ACCESS SHARE | Rare |
|
|
151
|
+
| `SHARE ROW EXCLUSIVE` | Row writes + SHARE | CREATE TRIGGER |
|
|
152
|
+
| `SHARE` | Row writes | CREATE INDEX (non-concurrent) |
|
|
153
|
+
| `SHARE UPDATE EXCLUSIVE` | Schema changes | VACUUM, ANALYZE, CREATE INDEX CONCURRENTLY |
|
|
154
|
+
| `ROW EXCLUSIVE` | ACCESS EXCLUSIVE, EXCLUSIVE, SHARE | INSERT, UPDATE, DELETE |
|
|
155
|
+
| `ROW SHARE` | ACCESS EXCLUSIVE, EXCLUSIVE | SELECT FOR UPDATE/SHARE |
|
|
156
|
+
| `ACCESS SHARE` | ACCESS EXCLUSIVE only | SELECT |
|
|
157
|
+
|
|
158
|
+
### Detecting lock conflicts
|
|
159
|
+
|
|
160
|
+
```sql
|
|
161
|
+
-- See current locks
|
|
162
|
+
SELECT pid, relation::regclass, mode, granted
|
|
163
|
+
FROM pg_locks
|
|
164
|
+
WHERE relation IS NOT NULL;
|
|
165
|
+
|
|
166
|
+
-- Find blocking queries
|
|
167
|
+
SELECT blocked.pid, blocked.query, blocking.pid AS blocking_pid, blocking.query
|
|
168
|
+
FROM pg_stat_activity blocked
|
|
169
|
+
JOIN pg_stat_activity blocking ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
|
|
170
|
+
WHERE NOT blocked.granted;
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Advisory locks
|
|
176
|
+
|
|
177
|
+
Application-level locks not tied to any table — useful for mutual exclusion across processes.
|
|
178
|
+
|
|
179
|
+
```sql
|
|
180
|
+
-- Session-level (auto-released on disconnect)
|
|
181
|
+
SELECT pg_advisory_lock(12345); -- exclusive
|
|
182
|
+
SELECT pg_advisory_lock_shared(12345); -- shared
|
|
183
|
+
SELECT pg_advisory_unlock(12345);
|
|
184
|
+
SELECT pg_advisory_unlock_all();
|
|
185
|
+
|
|
186
|
+
-- Transaction-level (auto-released at COMMIT/ROLLBACK)
|
|
187
|
+
SELECT pg_advisory_xact_lock(12345);
|
|
188
|
+
SELECT pg_advisory_xact_lock_shared(12345);
|
|
189
|
+
|
|
190
|
+
-- Try to acquire without blocking (returns bool)
|
|
191
|
+
SELECT pg_try_advisory_lock(12345);
|
|
192
|
+
|
|
193
|
+
-- Use hash of text for namespacing
|
|
194
|
+
SELECT pg_advisory_lock(hashtext('my-job-lock'));
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## MVCC
|
|
200
|
+
|
|
201
|
+
PostgreSQL uses Multi-Version Concurrency Control: readers never block writers; writers never block readers.
|
|
202
|
+
|
|
203
|
+
Key concepts:
|
|
204
|
+
|
|
205
|
+
- Each row has `xmin` (transaction that inserted) and `xmax` (transaction that deleted/updated).
|
|
206
|
+
- A transaction sees rows where `xmin` is committed and visible, and `xmax` is not yet committed.
|
|
207
|
+
- Dead tuples (old row versions) accumulate and must be reclaimed by `VACUUM`.
|
|
208
|
+
|
|
209
|
+
```sql
|
|
210
|
+
-- See transaction ID (xmin) of rows
|
|
211
|
+
SELECT *, xmin, xmax FROM users LIMIT 5;
|
|
212
|
+
|
|
213
|
+
-- Current transaction ID (txid_current() is deprecated since PG 13)
|
|
214
|
+
SELECT pg_current_xact_id();
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
For VACUUM and maintenance, see [performance.md](performance.md).
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Common patterns
|
|
222
|
+
|
|
223
|
+
### Optimistic locking (application-level)
|
|
224
|
+
|
|
225
|
+
```sql
|
|
226
|
+
-- Add version column
|
|
227
|
+
ALTER TABLE products ADD COLUMN version integer NOT NULL DEFAULT 0;
|
|
228
|
+
|
|
229
|
+
-- Read
|
|
230
|
+
SELECT id, price, version FROM products WHERE id = $1;
|
|
231
|
+
|
|
232
|
+
-- Update — fail if version changed since read
|
|
233
|
+
UPDATE products
|
|
234
|
+
SET price = $new_price, version = version + 1
|
|
235
|
+
WHERE id = $1 AND version = $expected_version;
|
|
236
|
+
-- Check affected rows: if 0, conflict detected → retry
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Queue processing with SKIP LOCKED
|
|
240
|
+
|
|
241
|
+
```sql
|
|
242
|
+
BEGIN;
|
|
243
|
+
SELECT id, payload FROM jobs
|
|
244
|
+
WHERE status = 'pending'
|
|
245
|
+
ORDER BY created_at
|
|
246
|
+
LIMIT 1
|
|
247
|
+
FOR UPDATE SKIP LOCKED;
|
|
248
|
+
|
|
249
|
+
-- Process the job...
|
|
250
|
+
|
|
251
|
+
UPDATE jobs SET status = 'done', processed_at = NOW() WHERE id = $1;
|
|
252
|
+
COMMIT;
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Deferred constraint checking
|
|
256
|
+
|
|
257
|
+
```sql
|
|
258
|
+
-- Useful for circular references or bulk data loading
|
|
259
|
+
BEGIN;
|
|
260
|
+
SET CONSTRAINTS ALL DEFERRED;
|
|
261
|
+
INSERT INTO a (id, b_id) VALUES (1, 2);
|
|
262
|
+
INSERT INTO b (id, a_id) VALUES (2, 1); -- FK to a(1) is deferred
|
|
263
|
+
COMMIT; -- constraints checked here
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Two-phase commit (distributed transactions)
|
|
267
|
+
|
|
268
|
+
```sql
|
|
269
|
+
-- Prepare
|
|
270
|
+
BEGIN;
|
|
271
|
+
UPDATE ...;
|
|
272
|
+
PREPARE TRANSACTION 'my-txn-id';
|
|
273
|
+
|
|
274
|
+
-- Commit or rollback from any connection
|
|
275
|
+
COMMIT PREPARED 'my-txn-id';
|
|
276
|
+
ROLLBACK PREPARED 'my-txn-id';
|
|
277
|
+
|
|
278
|
+
-- View prepared transactions
|
|
279
|
+
SELECT * FROM pg_prepared_xacts;
|
|
280
|
+
```
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-best-practices
|
|
3
|
+
description: "React and Next.js performance patterns. Use when writing, reviewing, or optimizing React components."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# React & Next.js Performance Patterns
|
|
7
|
+
|
|
8
|
+
Performance optimization guide for React and Next.js applications, based on Vercel Engineering practices. 8 categories organized by impact.
|
|
9
|
+
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
- [When to Apply](#when-to-apply)
|
|
13
|
+
- [Quick Reference](#quick-reference)
|
|
14
|
+
- [Async Patterns (CRITICAL)](#1-async-patterns-critical)
|
|
15
|
+
- [Bundle Optimization (CRITICAL)](#2-bundle-optimization-critical)
|
|
16
|
+
- [Server-Side Performance (HIGH)](#3-server-side-performance-high)
|
|
17
|
+
- [Client-Side Patterns (MEDIUM-HIGH)](#4-client-side-patterns-medium-high)
|
|
18
|
+
- [Re-render Optimization (MEDIUM)](#5-re-render-optimization-medium)
|
|
19
|
+
- [Rendering Performance (MEDIUM)](#6-rendering-performance-medium)
|
|
20
|
+
- [JavaScript Performance (LOW-MEDIUM)](#7-javascript-performance-low-medium)
|
|
21
|
+
- [Advanced Patterns (LOW)](#8-advanced-patterns-low)
|
|
22
|
+
|
|
23
|
+
## When to Apply
|
|
24
|
+
|
|
25
|
+
- Writing new React components or Next.js pages
|
|
26
|
+
- Implementing data fetching (client or server-side)
|
|
27
|
+
- Reviewing code for performance issues
|
|
28
|
+
- Optimizing bundle size or load times
|
|
29
|
+
|
|
30
|
+
## Quick Reference
|
|
31
|
+
|
|
32
|
+
### 1. Async Patterns (CRITICAL)
|
|
33
|
+
|
|
34
|
+
[references/async-patterns.md](references/async-patterns.md)
|
|
35
|
+
|
|
36
|
+
- Prevent waterfall chains in API routes -- start promises early, await late
|
|
37
|
+
- Defer await until needed -- move await into branches that use it
|
|
38
|
+
- Dependency-based parallelization -- `Promise.all()` with `.then()` chaining
|
|
39
|
+
- Strategic Suspense boundaries -- stream content with `<Suspense>`
|
|
40
|
+
|
|
41
|
+
### 2. Bundle Optimization (CRITICAL)
|
|
42
|
+
|
|
43
|
+
[references/bundle-optimization.md](references/bundle-optimization.md)
|
|
44
|
+
|
|
45
|
+
- Avoid barrel file imports -- import directly from source files
|
|
46
|
+
- Conditional module loading -- load only when feature is activated
|
|
47
|
+
- Defer non-critical third-party libraries -- load after hydration
|
|
48
|
+
- Dynamic imports for heavy components -- `next/dynamic` with `ssr: false`
|
|
49
|
+
- Preload on user intent -- preload on hover/focus
|
|
50
|
+
|
|
51
|
+
### 3. Server-Side Performance (HIGH)
|
|
52
|
+
|
|
53
|
+
[references/server-performance.md](references/server-performance.md)
|
|
54
|
+
|
|
55
|
+
- `after()` for non-blocking operations -- logging, analytics after response
|
|
56
|
+
- Authenticate Server Actions -- treat as public endpoints
|
|
57
|
+
- Cross-request LRU caching -- share data across sequential requests
|
|
58
|
+
- `React.cache()` deduplication -- per-request with primitive args
|
|
59
|
+
- Avoid duplicate RSC serialization -- transform in client, not server
|
|
60
|
+
- Parallel fetching via composition -- restructure component tree
|
|
61
|
+
- Minimize serialization at boundaries -- pass only needed fields
|
|
62
|
+
|
|
63
|
+
### 4. Client-Side Patterns (MEDIUM-HIGH)
|
|
64
|
+
|
|
65
|
+
[references/client-patterns.md](references/client-patterns.md)
|
|
66
|
+
|
|
67
|
+
- Deduplicate global event listeners -- `useSWRSubscription`
|
|
68
|
+
- Version and minimize localStorage -- schema versioning, try-catch
|
|
69
|
+
- Passive event listeners -- `{ passive: true }` for scroll performance
|
|
70
|
+
- SWR for automatic deduplication -- caching and revalidation
|
|
71
|
+
|
|
72
|
+
### 5. Re-render Optimization (MEDIUM)
|
|
73
|
+
|
|
74
|
+
[references/rerender-optimization.md](references/rerender-optimization.md)
|
|
75
|
+
|
|
76
|
+
- Defer state reads to usage point -- read in callbacks, not render
|
|
77
|
+
- Narrow effect dependencies -- use primitives, not objects
|
|
78
|
+
- Derive state during render -- no state + effect for computed values
|
|
79
|
+
- Functional setState -- stable callbacks, no stale closures
|
|
80
|
+
- Hoist default non-primitive props -- stable defaults for `memo()`
|
|
81
|
+
- Extract to memoized components -- skip computation with early returns
|
|
82
|
+
- Interaction logic in event handlers -- not state + effect
|
|
83
|
+
- useRef for transient values -- avoid re-render on frequent updates
|
|
84
|
+
|
|
85
|
+
### 6. Rendering Performance (MEDIUM)
|
|
86
|
+
|
|
87
|
+
[references/rendering-performance.md](references/rendering-performance.md)
|
|
88
|
+
|
|
89
|
+
- Animate SVG wrapper -- hardware-accelerated CSS on `<div>`, not `<svg>`
|
|
90
|
+
- CSS `content-visibility: auto` -- defer off-screen rendering
|
|
91
|
+
- Hoist static JSX -- extract constants outside components
|
|
92
|
+
- Prevent hydration mismatch -- inline script for client-only data
|
|
93
|
+
- `useTransition` over manual loading states -- built-in pending state
|
|
94
|
+
|
|
95
|
+
### 7. JavaScript Performance (LOW-MEDIUM)
|
|
96
|
+
|
|
97
|
+
[references/js-performance.md](references/js-performance.md)
|
|
98
|
+
|
|
99
|
+
- Avoid layout thrashing -- batch DOM reads and writes
|
|
100
|
+
- Cache repeated function calls -- module-level Map
|
|
101
|
+
- Cache storage API calls -- in-memory cache for localStorage/cookies
|
|
102
|
+
- Build index Maps for lookups -- O(1) instead of O(n) `.find()`
|
|
103
|
+
- Loop for min/max -- O(n) instead of O(n log n) sort
|
|
104
|
+
|
|
105
|
+
### 8. Advanced Patterns (LOW)
|
|
106
|
+
|
|
107
|
+
[references/advanced-patterns.md](references/advanced-patterns.md)
|
|
108
|
+
|
|
109
|
+
- Store event handlers in refs -- stable effect subscriptions
|
|
110
|
+
- Initialize app once per load -- module-level guard
|