@pgpm/achievements 0.4.0 → 0.6.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/Makefile CHANGED
@@ -1,5 +1,5 @@
1
1
  EXTENSION = launchql-achievements
2
- DATA = sql/launchql-achievements--0.4.6.sql
2
+ DATA = sql/launchql-achievements--0.5.0.sql
3
3
 
4
4
  PG_CONFIG = pg_config
5
5
  PGXS := $(shell $(PG_CONFIG) --pgxs)
package/README.md CHANGED
@@ -2,4 +2,345 @@
2
2
 
3
3
  Achievement system for tracking user progress and milestones.
4
4
 
5
- Provides functionality for creating, tracking, and managing user achievements, progress tracking, and milestone systems.
5
+ ## Overview
6
+
7
+ `@pgpm/achievements` provides a comprehensive achievement and progression system for PostgreSQL applications. This package enables automatic tracking of user actions, milestone completion, and level-based progression through trigger-based automation. It integrates with JWT claims for user context and provides a flexible framework for gamification and user engagement.
8
+
9
+ ## Features
10
+
11
+ - **Level-Based Progression**: Define achievement levels with specific requirements
12
+ - **Automatic Tracking**: Trigger-based achievement counting from any table
13
+ - **User Progress Queries**: Check completion status and remaining requirements
14
+ - **Row-Level Security**: Built-in RLS policies for user data isolation
15
+ - **JWT Integration**: Seamless user context via JWT claims
16
+ - **Flexible Requirements**: Support for multiple requirement types per level
17
+ - **Real-Time Updates**: Automatic achievement tallying via triggers
18
+
19
+ ## Installation
20
+
21
+ If you have `pgpm` installed:
22
+
23
+ ```bash
24
+ pgpm install @pgpm/achievements
25
+ pgpm deploy
26
+ ```
27
+
28
+ This is a quick way to get started. The sections below provide more detailed installation options.
29
+
30
+ ### Prerequisites
31
+
32
+ ```bash
33
+ # Install pgpm globally
34
+ npm install -g pgpm
35
+
36
+ # Start PostgreSQL
37
+ pgpm docker start
38
+
39
+ # Set environment variables
40
+ eval "$(pgpm env)"
41
+ ```
42
+
43
+ ### Deploy
44
+
45
+ #### Option 1: Deploy by installing with pgpm
46
+
47
+ ```bash
48
+ pgpm install @pgpm/achievements
49
+ pgpm deploy
50
+ ```
51
+
52
+ #### Option 2: Deploy from Package Directory
53
+
54
+ ```bash
55
+ cd packages/metrics/achievements
56
+ pgpm deploy --createdb
57
+ ```
58
+
59
+ #### Option 3: Deploy from Workspace Root
60
+
61
+ ```bash
62
+ # Install workspace dependencies
63
+ pnpm install
64
+
65
+ # Deploy with dependencies
66
+ pgpm deploy mydb1 --yes --createdb
67
+ ```
68
+
69
+ ## Core Concepts
70
+
71
+ ### Levels
72
+ Define progression stages (e.g., 'newbie', 'intermediate', 'expert') in the `status_public.levels` table.
73
+
74
+ ### Level Requirements
75
+ Specify what actions users must complete for each level in `status_public.level_requirements`:
76
+ - **name**: Action identifier (e.g., 'complete_profile', 'upload_photo')
77
+ - **level**: Which level this requirement belongs to
78
+ - **required_count**: How many times the action must be performed
79
+ - **priority**: Display order for requirements
80
+
81
+ ### User Achievements
82
+ Automatically maintained table tracking user progress in `status_public.user_achievements`:
83
+ - Updated by trigger functions
84
+ - Tallies completion counts per user per action
85
+ - Should not be manually modified
86
+
87
+ ### User Steps
88
+ Individual action records in `status_public.user_steps` for detailed tracking.
89
+
90
+ ## Usage
91
+
92
+ ### Setting Up Levels and Requirements
93
+
94
+ ```sql
95
+ -- Create achievement levels
96
+ INSERT INTO status_public.levels (name) VALUES
97
+ ('newbie'),
98
+ ('intermediate'),
99
+ ('expert');
100
+
101
+ -- Define requirements for newbie level
102
+ INSERT INTO status_public.level_requirements (name, level, required_count, priority) VALUES
103
+ ('complete_profile', 'newbie', 1, 1),
104
+ ('upload_photo', 'newbie', 1, 2),
105
+ ('make_first_post', 'newbie', 1, 3);
106
+
107
+ -- Define requirements for intermediate level
108
+ INSERT INTO status_public.level_requirements (name, level, required_count, priority) VALUES
109
+ ('make_first_post', 'intermediate', 10, 1),
110
+ ('receive_likes', 'intermediate', 50, 2);
111
+ ```
112
+
113
+ ### Adding Achievement Triggers
114
+
115
+ Use trigger functions to automatically track achievements when users perform actions:
116
+
117
+ #### tg_achievement
118
+ Increments achievement on any column change:
119
+
120
+ ```sql
121
+ CREATE TRIGGER track_profile_completion
122
+ AFTER UPDATE ON users
123
+ FOR EACH ROW
124
+ EXECUTE FUNCTION status_private.tg_achievement('bio', 'complete_profile');
125
+ ```
126
+
127
+ #### tg_achievement_toggle
128
+ Increments achievement on NULL → value transition (first-time actions):
129
+
130
+ ```sql
131
+ CREATE TRIGGER track_photo_upload
132
+ AFTER UPDATE ON users
133
+ FOR EACH ROW
134
+ EXECUTE FUNCTION status_private.tg_achievement_toggle('profile_image', 'upload_photo');
135
+ ```
136
+
137
+ #### tg_achievement_boolean
138
+ Increments achievement when column becomes TRUE:
139
+
140
+ ```sql
141
+ CREATE TRIGGER track_email_verification
142
+ AFTER UPDATE ON users
143
+ FOR EACH ROW
144
+ EXECUTE FUNCTION status_private.tg_achievement_boolean('email_verified', 'verify_email');
145
+ ```
146
+
147
+ #### tg_achievement_toggle_boolean
148
+ Increments only on FALSE/NULL → TRUE transition:
149
+
150
+ ```sql
151
+ CREATE TRIGGER track_terms_acceptance
152
+ AFTER UPDATE ON users
153
+ FOR EACH ROW
154
+ EXECUTE FUNCTION status_private.tg_achievement_toggle_boolean('terms_accepted', 'accept_terms');
155
+ ```
156
+
157
+ ### Checking User Progress
158
+
159
+ ```sql
160
+ -- Check what steps remain for a user to reach a level
161
+ SELECT * FROM status_public.steps_required('newbie', 'user-uuid');
162
+
163
+ -- Check if user has achieved a level
164
+ SELECT status_public.user_achieved('newbie', 'user-uuid');
165
+
166
+ -- View user's current achievements
167
+ SELECT * FROM status_public.user_achievements
168
+ WHERE user_id = 'user-uuid';
169
+ ```
170
+
171
+ ### Using JWT Context
172
+
173
+ The package integrates with `@pgpm/jwt-claims` for automatic user context:
174
+
175
+ ```sql
176
+ -- Check current user's progress (uses JWT claims)
177
+ SELECT * FROM status_public.steps_required('newbie');
178
+
179
+ -- Check if current user achieved level
180
+ SELECT status_public.user_achieved('intermediate');
181
+ ```
182
+
183
+ ## Functions Reference
184
+
185
+ ### status_public.steps_required(level_name, user_id)
186
+ Returns remaining requirements for a user to complete a level.
187
+
188
+ **Parameters:**
189
+ - `level_name` (text): Level to check
190
+ - `user_id` (uuid): User identifier (defaults to current JWT user)
191
+
192
+ **Returns:** Set of level_requirements with remaining counts
193
+
194
+ ### status_public.user_achieved(level_name, user_id)
195
+ Checks if user has completed all requirements for a level.
196
+
197
+ **Parameters:**
198
+ - `level_name` (text): Level to check
199
+ - `user_id` (uuid): User identifier (defaults to current JWT user)
200
+
201
+ **Returns:** Boolean indicating completion status
202
+
203
+ ## Trigger Functions
204
+
205
+ ### status_private.tg_achievement(column_name, achievement_name)
206
+ Increments achievement on any column change.
207
+
208
+ ### status_private.tg_achievement_toggle(column_name, achievement_name)
209
+ Increments achievement on NULL → value transition.
210
+
211
+ ### status_private.tg_achievement_boolean(column_name, achievement_name)
212
+ Increments achievement when column becomes TRUE.
213
+
214
+ ### status_private.tg_achievement_toggle_boolean(column_name, achievement_name)
215
+ Increments achievement on FALSE/NULL → TRUE transition.
216
+
217
+ ## Example: Complete Achievement System
218
+
219
+ ```sql
220
+ -- 1. Set up levels
221
+ INSERT INTO status_public.levels (name) VALUES ('beginner'), ('pro');
222
+
223
+ -- 2. Define requirements
224
+ INSERT INTO status_public.level_requirements (name, level, required_count, priority) VALUES
225
+ ('complete_profile', 'beginner', 1, 1),
226
+ ('make_post', 'beginner', 3, 2),
227
+ ('make_post', 'pro', 50, 1),
228
+ ('receive_likes', 'pro', 100, 2);
229
+
230
+ -- 3. Add triggers to track actions
231
+ CREATE TRIGGER track_profile
232
+ AFTER UPDATE ON users
233
+ FOR EACH ROW
234
+ EXECUTE FUNCTION status_private.tg_achievement_toggle('bio', 'complete_profile');
235
+
236
+ CREATE TRIGGER track_posts
237
+ AFTER INSERT ON posts
238
+ FOR EACH ROW
239
+ EXECUTE FUNCTION status_private.tg_achievement('id', 'make_post');
240
+
241
+ CREATE TRIGGER track_likes
242
+ AFTER INSERT ON likes
243
+ FOR EACH ROW
244
+ EXECUTE FUNCTION status_private.tg_achievement('id', 'receive_likes');
245
+
246
+ -- 4. Check user progress
247
+ SELECT * FROM status_public.steps_required('beginner', 'user-uuid');
248
+ SELECT status_public.user_achieved('beginner', 'user-uuid');
249
+ ```
250
+
251
+ ## Dependencies
252
+
253
+ - `@pgpm/jwt-claims`: JWT claim handling for user context
254
+ - `@pgpm/verify`: Verification utilities
255
+
256
+ ## Testing
257
+
258
+ ```bash
259
+ pnpm test
260
+ ```
261
+
262
+ ## Development
263
+
264
+ See the [Development](#development) section below for information on working with this package.
265
+
266
+ ---
267
+
268
+ ## Development
269
+
270
+ ### **Before You Begin**
271
+
272
+ ```bash
273
+ # 1. Install pgpm
274
+ npm install -g pgpm
275
+
276
+ # 2. Start Postgres (Docker or local)
277
+ pgpm docker start
278
+
279
+ # 3. Load PG* environment variables (PGHOST, PGUSER, ...)
280
+ eval "$(pgpm env)"
281
+ ```
282
+
283
+ ---
284
+
285
+ ### **Starting a New Project**
286
+
287
+ ```bash
288
+ # 1. Create a workspace
289
+ pgpm init --workspace
290
+ cd my-app
291
+
292
+ # 2. Create your first module
293
+ pgpm init
294
+
295
+ # 3. Add a migration
296
+ pgpm add some_change
297
+
298
+ # 4. Deploy (auto-creates database)
299
+ pgpm deploy --createdb
300
+ ```
301
+
302
+ ---
303
+
304
+ ### **Working With an Existing Project**
305
+
306
+ ```bash
307
+ # 1. Clone and enter the project
308
+ git clone <repo> && cd <project>
309
+
310
+ # 2. Install dependencies
311
+ pnpm install
312
+
313
+ # 3. Deploy locally
314
+ pgpm deploy --createdb
315
+ ```
316
+
317
+ ---
318
+
319
+ ### **Testing a Module Inside a Workspace**
320
+
321
+ ```bash
322
+ # 1. Install workspace deps
323
+ pnpm install
324
+
325
+ # 2. Enter the module directory
326
+ cd packages/<some-module>
327
+
328
+ # 3. Run tests in watch mode
329
+ pnpm test:watch
330
+ ```
331
+
332
+ ## Related Tooling
333
+
334
+ * [pgpm](https://github.com/launchql/launchql/tree/main/packages/pgpm): **🖥️ PostgreSQL Package Manager** for modular Postgres development. Works with database workspaces, scaffolding, migrations, seeding, and installing database packages.
335
+ * [pgsql-test](https://github.com/launchql/launchql/tree/main/packages/pgsql-test): **📊 Isolated testing environments** with per-test transaction rollbacks—ideal for integration tests, complex migrations, and RLS simulation.
336
+ * [supabase-test](https://github.com/launchql/launchql/tree/main/packages/supabase-test): **🧪 Supabase-native test harness** preconfigured for the local Supabase stack—per-test rollbacks, JWT/role context helpers, and CI/GitHub Actions ready.
337
+ * [graphile-test](https://github.com/launchql/launchql/tree/main/packages/graphile-test): **🔐 Authentication mocking** for Graphile-focused test helpers and emulating row-level security contexts.
338
+ * [pgsql-parser](https://github.com/launchql/pgsql-parser): **🔄 SQL conversion engine** that interprets and converts PostgreSQL syntax.
339
+ * [libpg-query-node](https://github.com/launchql/libpg-query-node): **🌉 Node.js bindings** for `libpg_query`, converting SQL into parse trees.
340
+ * [pg-proto-parser](https://github.com/launchql/pg-proto-parser): **📦 Protobuf parser** for parsing PostgreSQL Protocol Buffers definitions to generate TypeScript interfaces, utility functions, and JSON mappings for enums.
341
+
342
+ ## Disclaimer
343
+
344
+ AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.
345
+
346
+ No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.
@@ -1,6 +1,6 @@
1
1
  # launchql-achievements extension
2
2
  comment = 'launchql-achievements extension'
3
- default_version = '0.4.6'
3
+ default_version = '0.5.0'
4
4
  module_pathname = '$libdir/launchql-achievements'
5
5
  requires = 'plpgsql,uuid-ossp,launchql-jwt-claims,launchql-verify'
6
6
  relocatable = false
package/package.json CHANGED
@@ -1,29 +1,29 @@
1
1
  {
2
2
  "name": "@pgpm/achievements",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Achievement system for tracking user progress and milestones",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "scripts": {
9
- "bundle": "lql package",
9
+ "bundle": "pgpm package",
10
10
  "test": "jest",
11
11
  "test:watch": "jest --watch"
12
12
  },
13
13
  "dependencies": {
14
- "@pgpm/jwt-claims": "0.4.0",
15
- "@pgpm/verify": "0.4.0"
14
+ "@pgpm/jwt-claims": "0.6.0",
15
+ "@pgpm/verify": "0.6.0"
16
16
  },
17
17
  "devDependencies": {
18
- "@launchql/cli": "^4.9.0"
18
+ "pgpm": "^0.2.0"
19
19
  },
20
20
  "repository": {
21
21
  "type": "git",
22
- "url": "https://github.com/launchql/extensions"
22
+ "url": "https://github.com/launchql/pgpm-modules"
23
23
  },
24
- "homepage": "https://github.com/launchql/extensions",
24
+ "homepage": "https://github.com/launchql/pgpm-modules",
25
25
  "bugs": {
26
- "url": "https://github.com/launchql/extensions/issues"
26
+ "url": "https://github.com/launchql/pgpm-modules/issues"
27
27
  },
28
- "gitHead": "cc9f52a335caa6e21ee7751b04b77c84ce6cb809"
28
+ "gitHead": "c7d0eae588d7a764b382a330c8b853b341b13fb2"
29
29
  }
package/sqitch.plan DELETED
@@ -1,20 +0,0 @@
1
- %syntax-version=1.0.0
2
- %project=launchql-achievements
3
- %uri=launchql-achievements
4
-
5
- schemas/status_private/schema [launchql-jwt-claims:schemas/jwt_public/procedures/current_user_id] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_private/schema
6
- schemas/status_public/schema 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/schema
7
- schemas/status_public/tables/user_steps/table [schemas/status_public/schema] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/tables/user_steps/table
8
- schemas/status_private/procedures/user_completed_step [schemas/status_private/schema schemas/status_public/tables/user_steps/table] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_private/procedures/user_completed_step
9
- schemas/status_private/procedures/user_incompleted_step [schemas/status_private/schema schemas/status_public/tables/user_steps/table] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_private/procedures/user_incompleted_step
10
- schemas/status_private/procedures/status_triggers [schemas/status_private/schema schemas/status_private/procedures/user_completed_step schemas/status_private/procedures/user_incompleted_step] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_private/procedures/status_triggers
11
- schemas/status_public/tables/user_achievements/table [schemas/status_public/schema] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/tables/user_achievements/table
12
- schemas/status_private/procedures/upsert_achievement [schemas/status_private/schema schemas/status_public/tables/user_achievements/table] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_private/procedures/upsert_achievement
13
- schemas/status_public/tables/levels/table [schemas/status_public/schema] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/tables/levels/table
14
- schemas/status_public/tables/level_requirements/table [schemas/status_public/schema schemas/status_public/tables/levels/table] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/tables/level_requirements/table
15
- schemas/status_public/procedures/steps_required [schemas/status_public/schema schemas/status_public/tables/level_requirements/table schemas/status_public/tables/user_achievements/table] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/procedures/steps_required
16
- schemas/status_public/procedures/user_achieved [schemas/status_public/schema schemas/status_public/procedures/steps_required schemas/status_public/tables/level_requirements/table schemas/status_public/tables/user_achievements/table] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/procedures/user_achieved
17
- schemas/status_public/tables/user_achievements/policies/enable_row_level_security [schemas/status_public/schema schemas/status_public/tables/user_achievements/table] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/tables/user_achievements/policies/enable_row_level_security
18
- schemas/status_public/tables/user_achievements/policies/user_achievements_policy [schemas/status_public/schema schemas/status_public/tables/user_achievements/table schemas/status_public/tables/user_achievements/policies/enable_row_level_security] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/tables/user_achievements/policies/user_achievements_policy
19
- schemas/status_public/tables/user_levels/table [schemas/status_public/schema] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/tables/user_levels/table
20
- schemas/status_public/tables/user_steps/triggers/update_achievements_tg [schemas/status_public/schema schemas/status_public/tables/user_steps/table schemas/status_public/tables/user_achievements/table schemas/status_private/procedures/upsert_achievement] 2017-08-11T08:11:51Z skitch <skitch@5b0c196eeb62> # add schemas/status_public/tables/user_steps/triggers/update_achievements_tg
File without changes