@itm-studio/partner-sdk 0.1.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 ADDED
@@ -0,0 +1,259 @@
1
+ # @itm-studio/partner-sdk
2
+
3
+ Type-safe TypeScript SDK for the ITM Partner API. Built with [genql](https://genql.dev/) — full autocomplete, zero introspection required.
4
+
5
+ [![CI](https://github.com/itm-studio/itm-partner-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/itm-studio/itm-partner-sdk/actions/workflows/ci.yml)
6
+ [![Schema Registry](https://img.shields.io/badge/schema-GraphQL%20Hive-blue)](https://app.graphql-hive.com/itm/itm-partner-api/production)
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @itm-studio/partner-sdk
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```typescript
17
+ import { createITMPartnerClient } from '@itm-studio/partner-sdk';
18
+
19
+ const itm = createITMPartnerClient({
20
+ token: process.env.ITM_PARTNER_TOKEN!,
21
+ });
22
+
23
+ // Get all upcoming moments for your brand
24
+ const { getPartnerMomentsForBrand } = await itm.query({
25
+ getPartnerMomentsForBrand: {
26
+ __args: { status: 'UPCOMING', take: 10 },
27
+ moments: {
28
+ uid: true,
29
+ name: true,
30
+ slug: true,
31
+ startDate: true,
32
+ endDate: true,
33
+ status: true,
34
+ venue: {
35
+ name: true,
36
+ city: true,
37
+ country: true,
38
+ },
39
+ ticketTiers: {
40
+ name: true,
41
+ price: true,
42
+ currency: { code: true, symbol: true },
43
+ remainingSupply: true,
44
+ },
45
+ },
46
+ totalCount: true,
47
+ hasNextPage: true,
48
+ nextCursor: true,
49
+ },
50
+ });
51
+ ```
52
+
53
+ ## Authentication
54
+
55
+ Get your partner API token from the ITM backstage dashboard: **Settings > Partner API**.
56
+
57
+ The token is sent as the `x-partner-api-key` header on every request. Your brand is determined automatically from the token — no need to pass brand IDs.
58
+
59
+ ## Available Queries
60
+
61
+ ### `getPartnerMomentsForBrand`
62
+
63
+ Get paginated moments (events) for your brand.
64
+
65
+ ```typescript
66
+ const { getPartnerMomentsForBrand } = await itm.query({
67
+ getPartnerMomentsForBrand: {
68
+ __args: {
69
+ take: 20, // items per page (default: 50)
70
+ cursor: nextCursor, // from previous response
71
+ status: 'UPCOMING', // UPCOMING | LIVE | ENDED
72
+ sortOrder: 'ASC', // ASC | DESC (by start date)
73
+ },
74
+ moments: { uid: true, name: true, startDate: true },
75
+ totalCount: true,
76
+ hasNextPage: true,
77
+ nextCursor: true,
78
+ },
79
+ });
80
+ ```
81
+
82
+ ### `getPartnerMoment`
83
+
84
+ Get a single moment by slug.
85
+
86
+ ```typescript
87
+ const { getPartnerMoment } = await itm.query({
88
+ getPartnerMoment: {
89
+ __args: { slug: 'my-event-slug' },
90
+ uid: true,
91
+ name: true,
92
+ startDate: true,
93
+ endDate: true,
94
+ ticketTiers: {
95
+ name: true,
96
+ price: true,
97
+ numSold: true,
98
+ remainingSupply: true,
99
+ },
100
+ },
101
+ });
102
+ ```
103
+
104
+ ### `getPartnerTicketsForMoment`
105
+
106
+ Get paginated tickets for a moment.
107
+
108
+ ```typescript
109
+ const { getPartnerTicketsForMoment } = await itm.query({
110
+ getPartnerTicketsForMoment: {
111
+ __args: {
112
+ momentSlug: 'my-event-slug',
113
+ checkedIn: true, // optional: filter by check-in status
114
+ take: 50,
115
+ },
116
+ tickets: {
117
+ uid: true,
118
+ price: true,
119
+ redeemedAt: true,
120
+ hasExpired: true,
121
+ user: { uid: true, name: true, primaryEmail: true },
122
+ ticketTier: { name: true, price: true },
123
+ payment: { amount: true, status: true },
124
+ },
125
+ totalCount: true,
126
+ hasNextPage: true,
127
+ nextCursor: true,
128
+ },
129
+ });
130
+ ```
131
+
132
+ ### `getPartnerCustomersForMoment`
133
+
134
+ Get paginated customers (users with their tickets) for a moment.
135
+
136
+ ```typescript
137
+ const { getPartnerCustomersForMoment } = await itm.query({
138
+ getPartnerCustomersForMoment: {
139
+ __args: { momentSlug: 'my-event-slug', take: 50 },
140
+ customers: {
141
+ user: { uid: true, name: true, primaryEmail: true, phoneNumber: true },
142
+ tickets: { uid: true, price: true, redeemedAt: true },
143
+ },
144
+ totalCount: true,
145
+ hasNextPage: true,
146
+ nextCursor: true,
147
+ },
148
+ });
149
+ ```
150
+
151
+ ## Pagination
152
+
153
+ All list endpoints use cursor-based pagination:
154
+
155
+ ```typescript
156
+ let cursor: string | null = null;
157
+
158
+ do {
159
+ const { getPartnerTicketsForMoment } = await itm.query({
160
+ getPartnerTicketsForMoment: {
161
+ __args: { momentSlug: 'my-event', cursor, take: 50 },
162
+ tickets: { uid: true, user: { name: true } },
163
+ hasNextPage: true,
164
+ nextCursor: true,
165
+ totalCount: true,
166
+ },
167
+ });
168
+
169
+ for (const ticket of getPartnerTicketsForMoment.tickets) {
170
+ console.log(ticket.user.name);
171
+ }
172
+
173
+ cursor = getPartnerTicketsForMoment.nextCursor ?? null;
174
+ } while (cursor);
175
+ ```
176
+
177
+ ## Custom Base URL
178
+
179
+ For staging or local development:
180
+
181
+ ```typescript
182
+ const itm = createITMPartnerClient({
183
+ token: process.env.ITM_PARTNER_TOKEN!,
184
+ baseUrl: 'https://staging-api.itm.studio/graphql',
185
+ });
186
+ ```
187
+
188
+ ## Development
189
+
190
+ ```bash
191
+ npm install
192
+ npm run generate # Generate typed client from schema
193
+ npm test # Run tests
194
+ npm run build # Build for publishing
195
+ ```
196
+
197
+ ## Architecture
198
+
199
+ ```
200
+ itm-backend (NestJS) itm-partner-sdk
201
+ ┌─────────────────────┐ ┌────────────────────────┐
202
+ │ Full GraphQL Schema │ │ schema/partner.graphql │
203
+ │ (8000+ lines) │ ── export ──▶ │ (partner subset only) │
204
+ │ │ │ │
205
+ │ BrandPartnerGuard │ │ genql │
206
+ │ x-partner-api-key │ │ │ │
207
+ │ Authorization Bearer │ │ ▼ │
208
+ └─────────────────────┘ │ src/generated/ (typed) │
209
+ ▲ │ │ │
210
+ │ │ ▼ │
211
+ │ x-partner-api-key │ createITMPartnerClient │
212
+ └──────────────────────────────│ │
213
+ └────────────────────────┘
214
+ │
215
+ ▼
216
+ ┌────────────────────────┐
217
+ │ GraphQL Hive │
218
+ │ Schema Registry │
219
+ │ Breaking change guard │
220
+ └────────────────────────┘
221
+ ```
222
+
223
+ - **Partner schema** is a curated subset of the full backend schema — only partner-safe endpoints
224
+ - **genql** generates a fully typed client from the schema at build time — no runtime introspection
225
+ - **GraphQL Hive** validates schema changes on every PR and blocks breaking changes
226
+ - **Authentication** uses the existing `BrandPartnerGuard` — token sent via `x-partner-api-key` header
227
+
228
+ ## Schema Governance (Hive)
229
+
230
+ This SDK uses [GraphQL Hive](https://the-guild.dev/graphql/hive) for schema governance.
231
+
232
+ - **On PRs**: `schema:check` runs automatically to detect breaking changes before merge
233
+ - **On push to main**: `schema:publish` updates the registry so the schema history is tracked
234
+ - **Dashboard**: [app.graphql-hive.com/itm/itm-partner-api/production](https://app.graphql-hive.com/itm/itm-partner-api/production)
235
+
236
+ ```bash
237
+ # Local usage (requires HIVE_TOKEN env var)
238
+ npm run schema:check # Check for breaking changes
239
+ npm run schema:publish # Publish schema to registry
240
+ ```
241
+
242
+ ## CI/CD
243
+
244
+ | Job | Trigger | What it does |
245
+ |---|---|---|
246
+ | `build-and-test` | Every push & PR | Install, generate, lint, test, build |
247
+ | `schema-check` | PRs only | Validates schema changes won't break partners |
248
+ | `schema-publish` | Push to main | Publishes schema to Hive registry |
249
+ | `publish` | Push to main | Auto-bumps patch version and publishes to NPM |
250
+
251
+ ## Adding New Partner Endpoints
252
+
253
+ When exposing a new backend endpoint to partners:
254
+
255
+ 1. Add the query/mutation to `schema/partner.graphql` with only the fields partners should access
256
+ 2. Run `npm run generate` to regenerate the typed client
257
+ 3. Add tests in `tests/queries.test.ts`
258
+ 4. Open a PR — Hive will validate the schema change isn't breaking
259
+ 5. After merge, the schema is auto-published to Hive and a new SDK version can be released