@cesar-richard/git-connector-sdk 1.28.0 → 1.30.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 CHANGED
@@ -62,9 +62,103 @@ Tokens with the `gck_` prefix are immutable once minted; revoke and reissue via
62
62
 
63
63
  ---
64
64
 
65
+ ## Activity tracking / CRA workflow
66
+
67
+ The `/v1/*` surface is designed to power activity reports (CRA, billable-time sheets, "what did I do this month"). The primitives below let you slice your data per-user, per-day, per-type.
68
+
69
+ ### What did I do today?
70
+
71
+ ```ts
72
+ const today = new Date().toISOString().slice(0, 10);
73
+ const { data } = await client.GET("/v1/events", {
74
+ params: { query: { from: today, to: today, user: "cesar" } },
75
+ });
76
+ for (const e of data.events) {
77
+ console.log(`[${e.day}] ${e.type} — ${e.title} (${e.repo})`);
78
+ }
79
+ ```
80
+
81
+ ### List my open PRs / MRs
82
+
83
+ ```ts
84
+ const { data } = await client.GET("/v1/activities", {
85
+ params: {
86
+ query: { author: "cesar", state: "open,draft", type: "pr,mr" },
87
+ },
88
+ });
89
+ for (const a of data.items) {
90
+ console.log(`${a.source}/${a.repo}#${a.number} — ${a.title} (${a.state})`);
91
+ }
92
+ ```
93
+
94
+ ### List issues I opened
95
+
96
+ ```ts
97
+ const { data } = await client.GET("/v1/work-items", {
98
+ params: { query: { author: "cesar", state: "open" } },
99
+ });
100
+ ```
101
+
102
+ ### Incremental polling (every 5 minutes)
103
+
104
+ Use `?since=<ISO>` to fetch only events newer than your last cursor:
105
+
106
+ ```ts
107
+ let cursor = "2026-05-18T00:00:00Z";
108
+ const { data } = await client.GET("/v1/events", {
109
+ params: {
110
+ query: { from: "2026-05-01", to: "2026-05-31", since: cursor },
111
+ },
112
+ });
113
+ if (data.events.length > 0) {
114
+ cursor = data.events[data.events.length - 1].occurredAt;
115
+ }
116
+ ```
117
+
118
+ ### Monthly CRA: count events per day
119
+
120
+ ```ts
121
+ const { data } = await client.GET("/v1/events", {
122
+ params: {
123
+ query: {
124
+ from: "2026-05-01",
125
+ to: "2026-05-31",
126
+ user: "cesar",
127
+ type: "commit,review,comment,state-transition",
128
+ },
129
+ },
130
+ });
131
+ const byDay: Record<string, number> = {};
132
+ for (const e of data.events) {
133
+ byDay[e.day] = (byDay[e.day] ?? 0) + 1;
134
+ }
135
+ ```
136
+
137
+ ### Reliability of the `author` field
138
+
139
+ `author` (on Activity and Event) is the **GitHub or GitLab account login** (e.g. `cesar`, never `César Richard`). If the underlying provider payload doesn't expose a login — rare cases like a git commit by an email not linked to any account — `author` is `null`. The git-config commit-author name is never used for `author`; it lives in `meta.commitAuthorName` when available, for display purposes only.
140
+
141
+ Filters like `?author=cesar` (on `/v1/activities` and `/v1/work-items`) and `?user=cesar` (on `/v1/events`) match the login exactly (case-insensitive). They do NOT fuzzy-match display names. This is a deliberate design choice for auditable activity tracking.
142
+
143
+ **GitLab resolver:** commits ingested via polling are resolved server-side by mapping `commit.author_email` → GL user login via the GitLab Users API. The result is cached (default TTL 90 days). If the email cannot be resolved (anonymous commit, email not associated with any GL user, private email on a self-hosted instance), `author` stays `null` and the git-config name lives in `meta.commitAuthorName`. Webhook-ingested GL commits use the pusher's username directly (no resolver needed).
144
+
145
+ **Structured author access via `authorResolved`:** commit events also carry an `authorResolved` blob with `{login, name, email}` (each nullable) — a single typed accessor that aggregates everything we know about the author:
146
+
147
+ ```ts
148
+ for (const e of data.events) {
149
+ if (e.type !== "commit") continue;
150
+ const { login, name, email } = e.authorResolved ?? {};
151
+ console.log(`${login ?? "anonymous"} (${name ?? "?"} <${email ?? "?"}>)`);
152
+ }
153
+ ```
154
+
155
+ Available on every commit event regardless of provider or ingestion path. `event.author` is always equal to `event.authorResolved?.login`.
156
+
157
+ ---
158
+
65
159
  ## API surface
66
160
 
67
- The `/v1/*` API exposes four resources: work items, iterations, work-item details, and the unified events stream.
161
+ The `/v1/*` API exposes five resources: work items, iterations, work-item details, the unified events stream, and raw activities.
68
162
 
69
163
  ### `GET /v1/work-items` — list aggregated work items
70
164
 
package/dist/schema.d.ts CHANGED
@@ -68,10 +68,61 @@ export interface paths {
68
68
  patch?: never;
69
69
  trace?: never;
70
70
  };
71
+ "/v1/activities": {
72
+ parameters: {
73
+ query?: never;
74
+ header?: never;
75
+ path?: never;
76
+ cookie?: never;
77
+ };
78
+ get: operations["getV1Activities"];
79
+ put?: never;
80
+ post?: never;
81
+ delete?: never;
82
+ options?: never;
83
+ head?: never;
84
+ patch?: never;
85
+ trace?: never;
86
+ };
71
87
  }
72
88
  export type webhooks = Record<string, never>;
73
89
  export interface components {
74
90
  schemas: {
91
+ ActivitiesListResponse: {
92
+ items: {
93
+ id: string;
94
+ source: "github" | "gitlab";
95
+ repo: string;
96
+ type: "pr" | "mr" | "issue";
97
+ number: string | number;
98
+ title: string;
99
+ body: string | null;
100
+ url: string;
101
+ state: "open" | "draft" | "merged" | "closed" | "unknown";
102
+ author: string | null;
103
+ createdAt: string;
104
+ updatedAt: string;
105
+ mergedAt: string | null;
106
+ }[];
107
+ total: string | number;
108
+ limit: string | number;
109
+ offset: string | number;
110
+ };
111
+ Activity: {
112
+ id: string;
113
+ source: "github" | "gitlab";
114
+ repo: string;
115
+ type: "pr" | "mr" | "issue";
116
+ number: string | number;
117
+ title: string;
118
+ body: string | null;
119
+ url: string;
120
+ state: "open" | "draft" | "merged" | "closed" | "unknown";
121
+ author: string | null;
122
+ createdAt: string;
123
+ updatedAt: string;
124
+ mergedAt: string | null;
125
+ };
75
126
  ActivityIteration: {
76
127
  id: string | number;
77
128
  title: string;
@@ -109,6 +160,11 @@ export interface components {
109
160
  meta: {
110
161
  [key: string]: unknown;
111
162
  } | null;
163
+ authorResolved?: {
164
+ login: string | null;
165
+ name: string | null;
166
+ email: string | null;
167
+ };
112
168
  }[];
113
169
  total: string | number;
114
170
  nextCursor: string | null;
@@ -129,6 +185,11 @@ export interface components {
129
185
  meta: {
130
186
  [key: string]: unknown;
131
187
  } | null;
188
+ authorResolved?: {
189
+ login: string | null;
190
+ name: string | null;
191
+ email: string | null;
192
+ };
132
193
  };
133
194
  IterationWithCount: {
134
195
  id: string | number;
@@ -254,6 +315,7 @@ export interface components {
254
315
  body: string | null;
255
316
  url: string;
256
317
  state: "open" | "closed" | "unknown";
318
+ author: string | null;
257
319
  createdAt: string;
258
320
  updatedAt: string;
259
321
  iteration: {
@@ -351,6 +413,7 @@ export interface components {
351
413
  body: string | null;
352
414
  url: string;
353
415
  state: "open" | "closed" | "unknown";
416
+ author: string | null;
354
417
  createdAt: string;
355
418
  updatedAt: string;
356
419
  iteration: {
@@ -460,6 +523,8 @@ export interface operations {
460
523
  source?: string;
461
524
  projectKey?: string;
462
525
  assignee?: string;
526
+ /** @description Filter by issue author login (case-insensitive). Useful for CRA: list issues opened by a specific user. */
527
+ author?: string;
463
528
  label?: string;
464
529
  labelScope?: string;
465
530
  search?: string;
@@ -493,6 +558,7 @@ export interface operations {
493
558
  body: string | null;
494
559
  url: string;
495
560
  state: "open" | "closed" | "unknown";
561
+ author: string | null;
496
562
  createdAt: string;
497
563
  updatedAt: string;
498
564
  iteration: {
@@ -594,6 +660,7 @@ export interface operations {
594
660
  body: string | null;
595
661
  url: string;
596
662
  state: "open" | "closed" | "unknown";
663
+ author: string | null;
597
664
  createdAt: string;
598
665
  updatedAt: string;
599
666
  iteration: {
@@ -695,6 +762,7 @@ export interface operations {
695
762
  body: string | null;
696
763
  url: string;
697
764
  state: "open" | "closed" | "unknown";
765
+ author: string | null;
698
766
  createdAt: string;
699
767
  updatedAt: string;
700
768
  iteration: {
@@ -817,6 +885,7 @@ export interface operations {
817
885
  body: string | null;
818
886
  url: string;
819
887
  state: "open" | "closed" | "unknown";
888
+ author: string | null;
820
889
  createdAt: string;
821
890
  updatedAt: string;
822
891
  iteration: {
@@ -913,6 +982,7 @@ export interface operations {
913
982
  body: string | null;
914
983
  url: string;
915
984
  state: "open" | "closed" | "unknown";
985
+ author: string | null;
916
986
  createdAt: string;
917
987
  updatedAt: string;
918
988
  iteration: {
@@ -1009,6 +1079,7 @@ export interface operations {
1009
1079
  body: string | null;
1010
1080
  url: string;
1011
1081
  state: "open" | "closed" | "unknown";
1082
+ author: string | null;
1012
1083
  createdAt: string;
1013
1084
  updatedAt: string;
1014
1085
  iteration: {
@@ -1194,6 +1265,8 @@ export interface operations {
1194
1265
  limit?: string;
1195
1266
  /** @description Opaque cursor from previous nextCursor. */
1196
1267
  cursor?: string;
1268
+ /** @description ISO datetime; returns only events with occurredAt > since. Combines with from/to. */
1269
+ since?: string;
1197
1270
  };
1198
1271
  header?: never;
1199
1272
  path?: never;
@@ -1223,6 +1296,11 @@ export interface operations {
1223
1296
  meta: {
1224
1297
  [key: string]: unknown;
1225
1298
  } | null;
1299
+ authorResolved?: {
1300
+ login: string | null;
1301
+ name: string | null;
1302
+ email: string | null;
1303
+ };
1226
1304
  }[];
1227
1305
  total: string | number;
1228
1306
  nextCursor: string | null;
@@ -1244,6 +1322,11 @@ export interface operations {
1244
1322
  meta: {
1245
1323
  [key: string]: unknown;
1246
1324
  } | null;
1325
+ authorResolved?: {
1326
+ login: string | null;
1327
+ name: string | null;
1328
+ email: string | null;
1329
+ };
1247
1330
  }[];
1248
1331
  total: string | number;
1249
1332
  nextCursor: string | null;
@@ -1265,6 +1348,11 @@ export interface operations {
1265
1348
  meta: {
1266
1349
  [key: string]: unknown;
1267
1350
  } | null;
1351
+ authorResolved?: {
1352
+ login: string | null;
1353
+ name: string | null;
1354
+ email: string | null;
1355
+ };
1268
1356
  }[];
1269
1357
  total: string | number;
1270
1358
  nextCursor: string | null;
@@ -1289,4 +1377,100 @@ export interface operations {
1289
1377
  };
1290
1378
  };
1291
1379
  };
1380
+ getV1Activities: {
1381
+ parameters: {
1382
+ query?: {
1383
+ /** @description Exact match (case-insensitive) on the activity author's GitHub/GitLab login. Does NOT match display names. */
1384
+ author?: string;
1385
+ /** @description CSV: open,draft,merged,closed,unknown. Default returns all states. */
1386
+ state?: string;
1387
+ /** @description CSV: pr,mr,issue. Default returns all. */
1388
+ type?: string;
1389
+ repo?: string;
1390
+ /** @description github | gitlab */
1391
+ provider?: string;
1392
+ /** @description ISO datetime; activity.updatedAt >= since. */
1393
+ updatedSince?: string;
1394
+ /** @description ISO datetime; activity.updatedAt < before. */
1395
+ updatedBefore?: string;
1396
+ /** @description Default 100, max 500. */
1397
+ limit?: string;
1398
+ /** @description Default 0. */
1399
+ offset?: string;
1400
+ };
1401
+ header?: never;
1402
+ path?: never;
1403
+ cookie?: never;
1404
+ };
1405
+ requestBody?: never;
1406
+ responses: {
1407
+ 200: {
1408
+ headers: {
1409
+ [name: string]: unknown;
1410
+ };
1411
+ content: {
1412
+ "application/json": {
1413
+ items: {
1414
+ id: string;
1415
+ source: "github" | "gitlab";
1416
+ repo: string;
1417
+ type: "pr" | "mr" | "issue";
1418
+ number: string | number;
1419
+ title: string;
1420
+ body: string | null;
1421
+ url: string;
1422
+ state: "open" | "draft" | "merged" | "closed" | "unknown";
1423
+ author: string | null;
1424
+ createdAt: string;
1425
+ updatedAt: string;
1426
+ mergedAt: string | null;
1427
+ }[];
1428
+ total: string | number;
1429
+ limit: string | number;
1430
+ offset: string | number;
1431
+ };
1432
+ "multipart/form-data": {
1433
+ items: {
1434
+ id: string;
1435
+ source: "github" | "gitlab";
1436
+ repo: string;
1437
+ type: "pr" | "mr" | "issue";
1438
+ number: string | number;
1439
+ title: string;
1440
+ body: string | null;
1441
+ url: string;
1442
+ state: "open" | "draft" | "merged" | "closed" | "unknown";
1443
+ author: string | null;
1444
+ createdAt: string;
1445
+ updatedAt: string;
1446
+ mergedAt: string | null;
1447
+ }[];
1448
+ total: string | number;
1449
+ limit: string | number;
1450
+ offset: string | number;
1451
+ };
1452
+ "text/plain": {
1453
+ items: {
1454
+ id: string;
1455
+ source: "github" | "gitlab";
1456
+ repo: string;
1457
+ type: "pr" | "mr" | "issue";
1458
+ number: string | number;
1459
+ title: string;
1460
+ body: string | null;
1461
+ url: string;
1462
+ state: "open" | "draft" | "merged" | "closed" | "unknown";
1463
+ author: string | null;
1464
+ createdAt: string;
1465
+ updatedAt: string;
1466
+ mergedAt: string | null;
1467
+ }[];
1468
+ total: string | number;
1469
+ limit: string | number;
1470
+ offset: string | number;
1471
+ };
1472
+ };
1473
+ };
1474
+ };
1475
+ };
1292
1476
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cesar-richard/git-connector-sdk",
3
- "version": "1.28.0",
3
+ "version": "1.30.0",
4
4
  "description": "TypeScript SDK for the git-connector v1 API (work items + iterations aggregated from GitHub/GitLab). Version published on npm tracks server releases.",
5
5
  "license": "MIT",
6
6
  "repository": {