@legendsoflearning/lol-sdk-core 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/dist/auth/index.d.mts +1 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.js +12 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +3 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/cache/index.d.mts +26 -0
- package/dist/cache/index.d.ts +26 -0
- package/dist/cache/index.js +63 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/index.mjs +60 -0
- package/dist/cache/index.mjs.map +1 -0
- package/dist/chunk-Q4UXELOU.mjs +284 -0
- package/dist/chunk-Q4UXELOU.mjs.map +1 -0
- package/dist/chunk-WWN77BBN.js +286 -0
- package/dist/chunk-WWN77BBN.js.map +1 -0
- package/dist/generated/admins/index.d.mts +2566 -0
- package/dist/generated/admins/index.d.ts +2566 -0
- package/dist/generated/admins/index.js +110 -0
- package/dist/generated/admins/index.js.map +1 -0
- package/dist/generated/admins/index.mjs +97 -0
- package/dist/generated/admins/index.mjs.map +1 -0
- package/dist/generated/developers/index.d.mts +330 -0
- package/dist/generated/developers/index.d.ts +330 -0
- package/dist/generated/developers/index.js +30 -0
- package/dist/generated/developers/index.js.map +1 -0
- package/dist/generated/developers/index.mjs +25 -0
- package/dist/generated/developers/index.mjs.map +1 -0
- package/dist/generated/parents/index.d.mts +1097 -0
- package/dist/generated/parents/index.d.ts +1097 -0
- package/dist/generated/parents/index.js +112 -0
- package/dist/generated/parents/index.js.map +1 -0
- package/dist/generated/parents/index.mjs +99 -0
- package/dist/generated/parents/index.mjs.map +1 -0
- package/dist/generated/play/index.d.mts +1060 -0
- package/dist/generated/play/index.d.ts +1060 -0
- package/dist/generated/play/index.js +109 -0
- package/dist/generated/play/index.js.map +1 -0
- package/dist/generated/play/index.mjs +96 -0
- package/dist/generated/play/index.mjs.map +1 -0
- package/dist/generated/public/index.d.mts +791 -0
- package/dist/generated/public/index.d.ts +791 -0
- package/dist/generated/public/index.js +39 -0
- package/dist/generated/public/index.js.map +1 -0
- package/dist/generated/public/index.mjs +33 -0
- package/dist/generated/public/index.mjs.map +1 -0
- package/dist/generated/teachers/index.d.mts +6205 -0
- package/dist/generated/teachers/index.d.ts +6205 -0
- package/dist/generated/teachers/index.js +353 -0
- package/dist/generated/teachers/index.js.map +1 -0
- package/dist/generated/teachers/index.mjs +282 -0
- package/dist/generated/teachers/index.mjs.map +1 -0
- package/dist/index-vM3xPKfV.d.mts +173 -0
- package/dist/index-vM3xPKfV.d.ts +173 -0
- package/dist/index.d.mts +154 -0
- package/dist/index.d.ts +154 -0
- package/dist/index.js +352 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +336 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +111 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkWWN77BBN_js = require('./chunk-WWN77BBN.js');
|
|
4
|
+
var client = require('@apollo/client');
|
|
5
|
+
var context = require('@apollo/client/link/context');
|
|
6
|
+
var error = require('@apollo/client/link/error');
|
|
7
|
+
var merge = require('deepmerge');
|
|
8
|
+
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var merge__default = /*#__PURE__*/_interopDefault(merge);
|
|
12
|
+
|
|
13
|
+
// src/api.ts
|
|
14
|
+
var API_ENDPOINTS = {
|
|
15
|
+
teachers: {
|
|
16
|
+
graphql: "/api2/teachers/graphql",
|
|
17
|
+
websocket: "/socket/websocket",
|
|
18
|
+
description: "Teacher dashboard and classroom management"
|
|
19
|
+
},
|
|
20
|
+
parents: {
|
|
21
|
+
graphql: "/api2/parents/graphql",
|
|
22
|
+
websocket: "/socket/websocket",
|
|
23
|
+
description: "Parent portal and home access management"
|
|
24
|
+
},
|
|
25
|
+
play: {
|
|
26
|
+
graphql: "/api2/play/graphql",
|
|
27
|
+
websocket: "/socket/websocket",
|
|
28
|
+
description: "Game play and assignment data"
|
|
29
|
+
},
|
|
30
|
+
public: {
|
|
31
|
+
graphql: "/api/public/graphql",
|
|
32
|
+
description: "Public/unauthenticated access"
|
|
33
|
+
},
|
|
34
|
+
developers: {
|
|
35
|
+
graphql: "/api/developers/graphql",
|
|
36
|
+
description: "Game developer portal"
|
|
37
|
+
},
|
|
38
|
+
admin: {
|
|
39
|
+
graphql: "/api/content/graphql",
|
|
40
|
+
description: "Admin content management"
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
function getEndpoint(api, baseUrl) {
|
|
44
|
+
const endpoint = API_ENDPOINTS[api];
|
|
45
|
+
return {
|
|
46
|
+
graphql: `${baseUrl}${endpoint.graphql}`,
|
|
47
|
+
websocket: endpoint.websocket ? `${baseUrl.replace("http", "ws")}${endpoint.websocket}` : void 0,
|
|
48
|
+
description: endpoint.description
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/errors.ts
|
|
53
|
+
var LolError = class _LolError extends Error {
|
|
54
|
+
code;
|
|
55
|
+
details;
|
|
56
|
+
constructor(message, code = "UNKNOWN", details) {
|
|
57
|
+
super(message);
|
|
58
|
+
this.name = "LolError";
|
|
59
|
+
this.code = code;
|
|
60
|
+
this.details = details;
|
|
61
|
+
Object.setPrototypeOf(this, _LolError.prototype);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var AuthError = class _AuthError extends LolError {
|
|
65
|
+
constructor(message, details) {
|
|
66
|
+
super(message, "NOT_AUTHENTICATED", details);
|
|
67
|
+
this.name = "AuthError";
|
|
68
|
+
Object.setPrototypeOf(this, _AuthError.prototype);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var NetworkError = class _NetworkError extends LolError {
|
|
72
|
+
statusCode;
|
|
73
|
+
constructor(message, statusCode, details) {
|
|
74
|
+
super(message, "NETWORK_ERROR", details);
|
|
75
|
+
this.name = "NetworkError";
|
|
76
|
+
this.statusCode = statusCode;
|
|
77
|
+
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
var GraphQLError = class _GraphQLError extends LolError {
|
|
81
|
+
locations;
|
|
82
|
+
path;
|
|
83
|
+
constructor(message, code, locations, path, details) {
|
|
84
|
+
super(message, code, details);
|
|
85
|
+
this.name = "GraphQLError";
|
|
86
|
+
this.locations = locations;
|
|
87
|
+
this.path = path;
|
|
88
|
+
Object.setPrototypeOf(this, _GraphQLError.prototype);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
function parseGraphQLErrors(errors) {
|
|
92
|
+
return errors.map((error) => {
|
|
93
|
+
const code = mapErrorMessageToCode(error.message);
|
|
94
|
+
return new GraphQLError(
|
|
95
|
+
error.message,
|
|
96
|
+
code,
|
|
97
|
+
error.locations,
|
|
98
|
+
error.path,
|
|
99
|
+
error.extensions
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function mapErrorMessageToCode(message) {
|
|
104
|
+
const lowered = message.toLowerCase();
|
|
105
|
+
if (lowered.includes("not authenticated") || lowered.includes("unauthorized")) {
|
|
106
|
+
return "NOT_AUTHENTICATED";
|
|
107
|
+
}
|
|
108
|
+
if (lowered.includes("not authorized") || lowered.includes("forbidden")) {
|
|
109
|
+
return "NOT_AUTHORIZED";
|
|
110
|
+
}
|
|
111
|
+
if (lowered.includes("not found")) {
|
|
112
|
+
return "NOT_FOUND";
|
|
113
|
+
}
|
|
114
|
+
if (lowered.includes("validation")) {
|
|
115
|
+
return "VALIDATION_ERROR";
|
|
116
|
+
}
|
|
117
|
+
return "UNKNOWN";
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/logger.ts
|
|
121
|
+
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
122
|
+
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
|
|
123
|
+
LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
|
|
124
|
+
LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
|
|
125
|
+
LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
|
|
126
|
+
LogLevel2[LogLevel2["NONE"] = 4] = "NONE";
|
|
127
|
+
return LogLevel2;
|
|
128
|
+
})(LogLevel || {});
|
|
129
|
+
var DefaultLogger = class {
|
|
130
|
+
level;
|
|
131
|
+
prefix;
|
|
132
|
+
constructor(config) {
|
|
133
|
+
this.level = config.level;
|
|
134
|
+
this.prefix = config.prefix ?? "[lol-sdk]";
|
|
135
|
+
}
|
|
136
|
+
debug(message, data) {
|
|
137
|
+
if (this.level <= 0 /* DEBUG */) {
|
|
138
|
+
console.debug(`${this.prefix} ${message}`, data ?? "");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
info(message, data) {
|
|
142
|
+
if (this.level <= 1 /* INFO */) {
|
|
143
|
+
console.info(`${this.prefix} ${message}`, data ?? "");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
warn(message, data) {
|
|
147
|
+
if (this.level <= 2 /* WARN */) {
|
|
148
|
+
console.warn(`${this.prefix} ${message}`, data ?? "");
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
error(message, data) {
|
|
152
|
+
if (this.level <= 3 /* ERROR */) {
|
|
153
|
+
console.error(`${this.prefix} ${message}`, data ?? "");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
function createLogger(config = {}) {
|
|
158
|
+
return new DefaultLogger({
|
|
159
|
+
level: config.level ?? 2 /* WARN */,
|
|
160
|
+
prefix: config.prefix
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/client.ts
|
|
165
|
+
var DEFAULT_BASE_URL = "https://api.legendsoflearning.com";
|
|
166
|
+
function createClient(config) {
|
|
167
|
+
const {
|
|
168
|
+
api,
|
|
169
|
+
baseUrl = DEFAULT_BASE_URL,
|
|
170
|
+
clientId,
|
|
171
|
+
mode,
|
|
172
|
+
cache: cacheConfig,
|
|
173
|
+
onError: errorHandler,
|
|
174
|
+
debug = false,
|
|
175
|
+
logLevel = debug ? 0 /* DEBUG */ : 2 /* WARN */,
|
|
176
|
+
logger = createLogger({ level: logLevel }),
|
|
177
|
+
ssr = typeof window === "undefined",
|
|
178
|
+
cookie
|
|
179
|
+
} = config;
|
|
180
|
+
const endpoint = getEndpoint(api, baseUrl);
|
|
181
|
+
const auth = chunkWWN77BBN_js.createAuth({ api, baseUrl, clientId, mode, ...config.auth });
|
|
182
|
+
logger.debug(`Creating client for ${api} API`, { endpoint });
|
|
183
|
+
const errorLink = error.onError(({ graphQLErrors, networkError, operation }) => {
|
|
184
|
+
if (graphQLErrors) {
|
|
185
|
+
const errors = parseGraphQLErrors(graphQLErrors);
|
|
186
|
+
errors.forEach((err) => {
|
|
187
|
+
logger.error(`[GraphQL error]: ${err.message}`, {
|
|
188
|
+
path: err.path,
|
|
189
|
+
operation: operation.operationName
|
|
190
|
+
});
|
|
191
|
+
if (err.code === "NOT_AUTHENTICATED") {
|
|
192
|
+
auth._handleAuthError();
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
errorHandler?.(errors[0]);
|
|
196
|
+
}
|
|
197
|
+
if (networkError) {
|
|
198
|
+
const err = new NetworkError(networkError.message);
|
|
199
|
+
logger.error(`[Network error]: ${err.message}`);
|
|
200
|
+
errorHandler?.(err);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
const csrfLink = context.setContext((_, { headers }) => {
|
|
204
|
+
if (ssr) return { headers };
|
|
205
|
+
const csrfToken = getCsrfToken();
|
|
206
|
+
return {
|
|
207
|
+
headers: {
|
|
208
|
+
...headers,
|
|
209
|
+
...csrfToken ? { "x-csrf-token": csrfToken } : {}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
const authLink = context.setContext((_, { headers }) => {
|
|
214
|
+
const authHeaders = {};
|
|
215
|
+
const modeHeaders = auth.getAuthHeaders();
|
|
216
|
+
Object.assign(authHeaders, modeHeaders);
|
|
217
|
+
if (ssr && cookie) {
|
|
218
|
+
authHeaders["Cookie"] = cookie;
|
|
219
|
+
}
|
|
220
|
+
if (!ssr && typeof localStorage !== "undefined") {
|
|
221
|
+
const playerToken = localStorage.getItem("player_token");
|
|
222
|
+
if (playerToken) {
|
|
223
|
+
authHeaders["x-player-token"] = playerToken;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
headers: {
|
|
228
|
+
...headers,
|
|
229
|
+
...authHeaders
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
const httpLink = client.createHttpLink({
|
|
234
|
+
uri: endpoint.graphql,
|
|
235
|
+
credentials: auth.getMode() === "cookie" ? "include" : "omit"
|
|
236
|
+
});
|
|
237
|
+
const link = client.from([errorLink, csrfLink, authLink, httpLink]);
|
|
238
|
+
const apolloClient = new client.ApolloClient({
|
|
239
|
+
ssrMode: ssr,
|
|
240
|
+
link,
|
|
241
|
+
cache: new client.InMemoryCache(cacheConfig)
|
|
242
|
+
});
|
|
243
|
+
return {
|
|
244
|
+
async query(document2, options = {}) {
|
|
245
|
+
logger.debug("Executing query", { variables: options.variables });
|
|
246
|
+
const result = await apolloClient.query({
|
|
247
|
+
query: document2,
|
|
248
|
+
variables: options.variables,
|
|
249
|
+
fetchPolicy: options.fetchPolicy,
|
|
250
|
+
errorPolicy: options.errorPolicy
|
|
251
|
+
});
|
|
252
|
+
return {
|
|
253
|
+
data: result.data,
|
|
254
|
+
loading: result.loading,
|
|
255
|
+
error: result.error,
|
|
256
|
+
networkStatus: result.networkStatus
|
|
257
|
+
};
|
|
258
|
+
},
|
|
259
|
+
async mutate(document2, options = {}) {
|
|
260
|
+
logger.debug("Executing mutation", { variables: options.variables });
|
|
261
|
+
const result = await apolloClient.mutate({
|
|
262
|
+
mutation: document2,
|
|
263
|
+
variables: options.variables,
|
|
264
|
+
optimisticResponse: options.optimisticResponse,
|
|
265
|
+
refetchQueries: options.refetchQueries,
|
|
266
|
+
awaitRefetchQueries: options.awaitRefetchQueries
|
|
267
|
+
});
|
|
268
|
+
return {
|
|
269
|
+
data: result.data ?? void 0,
|
|
270
|
+
loading: false,
|
|
271
|
+
error: result.errors?.[0] ? new Error(result.errors[0].message) : void 0,
|
|
272
|
+
called: true
|
|
273
|
+
};
|
|
274
|
+
},
|
|
275
|
+
auth,
|
|
276
|
+
cache: {
|
|
277
|
+
read(document2) {
|
|
278
|
+
try {
|
|
279
|
+
return apolloClient.readQuery({ query: document2 });
|
|
280
|
+
} catch {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
write(document2, data) {
|
|
285
|
+
apolloClient.writeQuery({ query: document2, data });
|
|
286
|
+
},
|
|
287
|
+
evict(id) {
|
|
288
|
+
return apolloClient.cache.evict({ id });
|
|
289
|
+
},
|
|
290
|
+
async reset() {
|
|
291
|
+
await apolloClient.resetStore();
|
|
292
|
+
},
|
|
293
|
+
async clear() {
|
|
294
|
+
await apolloClient.clearStore();
|
|
295
|
+
},
|
|
296
|
+
extract() {
|
|
297
|
+
return apolloClient.cache.extract();
|
|
298
|
+
},
|
|
299
|
+
restore(data) {
|
|
300
|
+
apolloClient.cache.restore(data);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
getApolloClient() {
|
|
304
|
+
return apolloClient;
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function getCsrfToken() {
|
|
309
|
+
if (typeof document === "undefined") return null;
|
|
310
|
+
const match = document.cookie.match(/(?:^|;\s*)_lol_csrf_token=([^;]*)/);
|
|
311
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
312
|
+
}
|
|
313
|
+
var APOLLO_STATE_PROP_NAME = "__APOLLO_STATE__";
|
|
314
|
+
function addApolloState(client, pageProps) {
|
|
315
|
+
return {
|
|
316
|
+
props: {
|
|
317
|
+
...pageProps.props,
|
|
318
|
+
[APOLLO_STATE_PROP_NAME]: client.cache.extract()
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function initializeClientWithState(config, initialState) {
|
|
323
|
+
const client = createClient(config);
|
|
324
|
+
if (initialState) {
|
|
325
|
+
const existingCache = client.cache.extract();
|
|
326
|
+
const mergedData = merge__default.default(existingCache, initialState, {
|
|
327
|
+
arrayMerge: (dest, src) => [
|
|
328
|
+
...src,
|
|
329
|
+
...dest.filter((d) => src.every((s) => !deepEqual(d, s)))
|
|
330
|
+
]
|
|
331
|
+
});
|
|
332
|
+
client.cache.restore(mergedData);
|
|
333
|
+
}
|
|
334
|
+
return client;
|
|
335
|
+
}
|
|
336
|
+
function deepEqual(a, b) {
|
|
337
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
exports.API_ENDPOINTS = API_ENDPOINTS;
|
|
341
|
+
exports.APOLLO_STATE_PROP_NAME = APOLLO_STATE_PROP_NAME;
|
|
342
|
+
exports.AuthError = AuthError;
|
|
343
|
+
exports.GraphQLError = GraphQLError;
|
|
344
|
+
exports.LogLevel = LogLevel;
|
|
345
|
+
exports.LolError = LolError;
|
|
346
|
+
exports.NetworkError = NetworkError;
|
|
347
|
+
exports.addApolloState = addApolloState;
|
|
348
|
+
exports.createClient = createClient;
|
|
349
|
+
exports.createLogger = createLogger;
|
|
350
|
+
exports.initializeClientWithState = initializeClientWithState;
|
|
351
|
+
//# sourceMappingURL=index.js.map
|
|
352
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api.ts","../src/errors.ts","../src/logger.ts","../src/client.ts"],"names":["LogLevel","createAuth","onError","setContext","createHttpLink","from","ApolloClient","InMemoryCache","document","merge"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * API endpoint definitions for Legends of Learning backend.\n */\n\nexport type ApiType =\n | 'teachers'\n | 'parents'\n | 'play'\n | 'public'\n | 'developers'\n | 'admin'\n\nexport interface ApiEndpoint {\n graphql: string\n websocket?: string\n description: string\n}\n\nexport const API_ENDPOINTS: Record<ApiType, ApiEndpoint> = {\n teachers: {\n graphql: '/api2/teachers/graphql',\n websocket: '/socket/websocket',\n description: 'Teacher dashboard and classroom management',\n },\n parents: {\n graphql: '/api2/parents/graphql',\n websocket: '/socket/websocket',\n description: 'Parent portal and home access management',\n },\n play: {\n graphql: '/api2/play/graphql',\n websocket: '/socket/websocket',\n description: 'Game play and assignment data',\n },\n public: {\n graphql: '/api/public/graphql',\n description: 'Public/unauthenticated access',\n },\n developers: {\n graphql: '/api/developers/graphql',\n description: 'Game developer portal',\n },\n admin: {\n graphql: '/api/content/graphql',\n description: 'Admin content management',\n },\n}\n\nexport function getEndpoint(api: ApiType, baseUrl: string): ApiEndpoint {\n const endpoint = API_ENDPOINTS[api]\n return {\n graphql: `${baseUrl}${endpoint.graphql}`,\n websocket: endpoint.websocket\n ? `${baseUrl.replace('http', 'ws')}${endpoint.websocket}`\n : undefined,\n description: endpoint.description,\n }\n}\n","/**\n * Error types for the Legends SDK.\n */\n\nexport type ErrorCode =\n | 'NOT_AUTHENTICATED'\n | 'NOT_AUTHORIZED'\n | 'NOT_FOUND'\n | 'VALIDATION_ERROR'\n | 'NETWORK_ERROR'\n | 'TIMEOUT'\n | 'RATE_LIMITED'\n | 'SERVER_ERROR'\n | 'UNKNOWN'\n\nexport class LolError extends Error {\n readonly code: ErrorCode\n readonly details?: Record<string, unknown>\n\n constructor(\n message: string,\n code: ErrorCode = 'UNKNOWN',\n details?: Record<string, unknown>\n ) {\n super(message)\n this.name = 'LolError'\n this.code = code\n this.details = details\n Object.setPrototypeOf(this, LolError.prototype)\n }\n}\n\nexport class AuthError extends LolError {\n constructor(message: string, details?: Record<string, unknown>) {\n super(message, 'NOT_AUTHENTICATED', details)\n this.name = 'AuthError'\n Object.setPrototypeOf(this, AuthError.prototype)\n }\n}\n\nexport class NetworkError extends LolError {\n readonly statusCode?: number\n\n constructor(\n message: string,\n statusCode?: number,\n details?: Record<string, unknown>\n ) {\n super(message, 'NETWORK_ERROR', details)\n this.name = 'NetworkError'\n this.statusCode = statusCode\n Object.setPrototypeOf(this, NetworkError.prototype)\n }\n}\n\nexport class GraphQLError extends LolError {\n readonly locations?: Array<{ line: number; column: number }>\n readonly path?: string[]\n\n constructor(\n message: string,\n code: ErrorCode,\n locations?: Array<{ line: number; column: number }>,\n path?: string[],\n details?: Record<string, unknown>\n ) {\n super(message, code, details)\n this.name = 'GraphQLError'\n this.locations = locations\n this.path = path\n Object.setPrototypeOf(this, GraphQLError.prototype)\n }\n}\n\nexport function parseGraphQLErrors(errors: any[]): GraphQLError[] {\n return errors.map((error) => {\n const code = mapErrorMessageToCode(error.message)\n return new GraphQLError(\n error.message,\n code,\n error.locations,\n error.path,\n error.extensions\n )\n })\n}\n\nfunction mapErrorMessageToCode(message: string): ErrorCode {\n const lowered = message.toLowerCase()\n if (lowered.includes('not authenticated') || lowered.includes('unauthorized')) {\n return 'NOT_AUTHENTICATED'\n }\n if (lowered.includes('not authorized') || lowered.includes('forbidden')) {\n return 'NOT_AUTHORIZED'\n }\n if (lowered.includes('not found')) {\n return 'NOT_FOUND'\n }\n if (lowered.includes('validation')) {\n return 'VALIDATION_ERROR'\n }\n return 'UNKNOWN'\n}\n","/**\n * Logging utilities for the Legends SDK.\n */\n\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n NONE = 4,\n}\n\nexport interface Logger {\n debug(message: string, data?: unknown): void\n info(message: string, data?: unknown): void\n warn(message: string, data?: unknown): void\n error(message: string, data?: unknown): void\n}\n\nexport interface LoggerConfig {\n level: LogLevel\n prefix?: string\n}\n\nclass DefaultLogger implements Logger {\n private level: LogLevel\n private prefix: string\n\n constructor(config: LoggerConfig) {\n this.level = config.level\n this.prefix = config.prefix ?? '[lol-sdk]'\n }\n\n debug(message: string, data?: unknown): void {\n if (this.level <= LogLevel.DEBUG) {\n console.debug(`${this.prefix} ${message}`, data ?? '')\n }\n }\n\n info(message: string, data?: unknown): void {\n if (this.level <= LogLevel.INFO) {\n console.info(`${this.prefix} ${message}`, data ?? '')\n }\n }\n\n warn(message: string, data?: unknown): void {\n if (this.level <= LogLevel.WARN) {\n console.warn(`${this.prefix} ${message}`, data ?? '')\n }\n }\n\n error(message: string, data?: unknown): void {\n if (this.level <= LogLevel.ERROR) {\n console.error(`${this.prefix} ${message}`, data ?? '')\n }\n }\n}\n\nexport function createLogger(config: Partial<LoggerConfig> = {}): Logger {\n return new DefaultLogger({\n level: config.level ?? LogLevel.WARN,\n prefix: config.prefix,\n })\n}\n\n// Silent logger for production\nexport const silentLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n}\n","/**\n * Main client implementation for the Legends SDK.\n */\n\nimport {\n ApolloClient,\n InMemoryCache,\n NormalizedCacheObject,\n createHttpLink,\n from,\n type InMemoryCacheConfig,\n type TypedDocumentNode,\n} from '@apollo/client'\nimport { setContext } from '@apollo/client/link/context'\nimport { onError } from '@apollo/client/link/error'\nimport merge from 'deepmerge'\n\nimport { type ApiType, getEndpoint } from './api'\nimport { createAuth, type Auth, type AuthConfig } from './auth'\nimport { NetworkError, parseGraphQLErrors } from './errors'\nimport { createLogger, LogLevel, type Logger } from './logger'\nimport type {\n QueryOptions,\n QueryResult,\n MutationOptions,\n MutationResult,\n} from './types'\n\nexport interface LolClientConfig {\n /**\n * Which API to connect to.\n */\n api: ApiType\n\n /**\n * Base URL for the API. Defaults to production.\n */\n baseUrl?: string\n\n /**\n * OAuth client ID for third-party apps.\n */\n clientId?: string\n\n /**\n * Authentication mode: 'cookie' (same-domain) or 'token' (cross-domain).\n */\n mode?: 'cookie' | 'token'\n\n /**\n * Authentication configuration.\n */\n auth?: AuthConfig\n\n /**\n * Apollo cache configuration.\n */\n cache?: InMemoryCacheConfig\n\n /**\n * Global error handler.\n */\n onError?: (error: Error) => void\n\n /**\n * Enable debug logging.\n */\n debug?: boolean\n\n /**\n * Log level.\n */\n logLevel?: LogLevel\n\n /**\n * Custom logger implementation.\n */\n logger?: Logger\n\n /**\n * Enable SSR mode.\n */\n ssr?: boolean\n\n /**\n * Cookies for SSR (from request).\n */\n cookie?: string\n}\n\nexport interface LolClient<_TApi extends ApiType = ApiType> {\n /**\n * Execute a GraphQL query.\n */\n query<TData, TVariables extends Record<string, unknown>>(\n document: TypedDocumentNode<TData, TVariables>,\n options?: QueryOptions<TVariables>\n ): Promise<QueryResult<TData>>\n\n /**\n * Execute a GraphQL mutation.\n */\n mutate<TData, TVariables extends Record<string, unknown>>(\n document: TypedDocumentNode<TData, TVariables>,\n options?: MutationOptions<TVariables>\n ): Promise<MutationResult<TData>>\n\n /**\n * Authentication module.\n */\n auth: Auth\n\n /**\n * Cache operations.\n */\n cache: {\n read<TData>(\n document: TypedDocumentNode<TData, Record<string, unknown>>\n ): TData | null\n write<TData>(\n document: TypedDocumentNode<TData, Record<string, unknown>>,\n data: TData\n ): void\n evict(id: string): boolean\n reset(): Promise<void>\n clear(): Promise<void>\n extract(): NormalizedCacheObject\n restore(data: NormalizedCacheObject): void\n }\n\n /**\n * Get the underlying Apollo client.\n */\n getApolloClient(): ApolloClient<NormalizedCacheObject>\n}\n\nconst DEFAULT_BASE_URL = 'https://api.legendsoflearning.com'\n\nexport function createClient<TApi extends ApiType>(\n config: LolClientConfig & { api: TApi }\n): LolClient<TApi> {\n const {\n api,\n baseUrl = DEFAULT_BASE_URL,\n clientId,\n mode,\n cache: cacheConfig,\n onError: errorHandler,\n debug = false,\n logLevel = debug ? LogLevel.DEBUG : LogLevel.WARN,\n logger = createLogger({ level: logLevel }),\n ssr = typeof window === 'undefined',\n cookie,\n } = config\n\n const endpoint = getEndpoint(api, baseUrl)\n const auth = createAuth({ api, baseUrl, clientId, mode, ...config.auth })\n\n logger.debug(`Creating client for ${api} API`, { endpoint })\n\n // Error handling link\n const errorLink = onError(({ graphQLErrors, networkError, operation }) => {\n if (graphQLErrors) {\n const errors = parseGraphQLErrors(graphQLErrors as unknown as any[])\n errors.forEach((err) => {\n logger.error(`[GraphQL error]: ${err.message}`, {\n path: err.path,\n operation: operation.operationName,\n })\n\n // Auto-handle auth errors\n if (err.code === 'NOT_AUTHENTICATED') {\n auth._handleAuthError()\n }\n })\n errorHandler?.(errors[0])\n }\n\n if (networkError) {\n const err = new NetworkError(networkError.message)\n logger.error(`[Network error]: ${err.message}`)\n errorHandler?.(err)\n }\n })\n\n // CSRF token link (client-side only)\n const csrfLink = setContext((_, { headers }) => {\n if (ssr) return { headers }\n\n const csrfToken = getCsrfToken()\n return {\n headers: {\n ...headers,\n ...(csrfToken ? { 'x-csrf-token': csrfToken } : {}),\n },\n }\n })\n\n // Auth token link - handles both cookie and token modes\n const authLink = setContext((_, { headers }) => {\n const authHeaders: Record<string, string> = {}\n\n // Get auth headers based on mode (cookie vs token)\n const modeHeaders = auth.getAuthHeaders()\n Object.assign(authHeaders, modeHeaders)\n\n // SSR: include cookies\n if (ssr && cookie) {\n authHeaders['Cookie'] = cookie\n }\n\n // Player token for anonymous play\n if (!ssr && typeof localStorage !== 'undefined') {\n const playerToken = localStorage.getItem('player_token')\n if (playerToken) {\n authHeaders['x-player-token'] = playerToken\n }\n }\n\n return {\n headers: {\n ...headers,\n ...authHeaders,\n },\n }\n })\n\n // HTTP link - credentials depend on auth mode\n const httpLink = createHttpLink({\n uri: endpoint.graphql,\n credentials: auth.getMode() === 'cookie' ? 'include' : 'omit',\n })\n\n // Compose links\n const link = from([errorLink, csrfLink, authLink, httpLink])\n\n // Create Apollo client\n const apolloClient = new ApolloClient({\n ssrMode: ssr,\n link,\n cache: new InMemoryCache(cacheConfig),\n })\n\n return {\n async query(document, options = {}) {\n logger.debug('Executing query', { variables: options.variables })\n\n const result = await apolloClient.query({\n query: document,\n variables: options.variables,\n fetchPolicy: options.fetchPolicy,\n errorPolicy: options.errorPolicy,\n })\n\n return {\n data: result.data,\n loading: result.loading,\n error: result.error,\n networkStatus: result.networkStatus,\n }\n },\n\n async mutate(document, options = {}) {\n logger.debug('Executing mutation', { variables: options.variables })\n\n const result = await apolloClient.mutate({\n mutation: document,\n variables: options.variables,\n optimisticResponse: options.optimisticResponse as any,\n refetchQueries: options.refetchQueries,\n awaitRefetchQueries: options.awaitRefetchQueries,\n })\n\n return {\n data: result.data ?? undefined,\n loading: false,\n error: result.errors?.[0] ? new Error(result.errors[0].message) : undefined,\n called: true,\n }\n },\n\n auth,\n\n cache: {\n read(document) {\n try {\n return apolloClient.readQuery({ query: document }) as any\n } catch {\n return null\n }\n },\n\n write(document, data) {\n apolloClient.writeQuery({ query: document, data: data as any })\n },\n\n evict(id) {\n return apolloClient.cache.evict({ id })\n },\n\n async reset() {\n await apolloClient.resetStore()\n },\n\n async clear() {\n await apolloClient.clearStore()\n },\n\n extract() {\n return apolloClient.cache.extract()\n },\n\n restore(data) {\n apolloClient.cache.restore(data)\n },\n },\n\n getApolloClient() {\n return apolloClient\n },\n }\n}\n\n// Utility: Get CSRF token from cookie\nfunction getCsrfToken(): string | null {\n if (typeof document === 'undefined') return null\n\n const match = document.cookie.match(/(?:^|;\\s*)_lol_csrf_token=([^;]*)/)\n return match ? decodeURIComponent(match[1]) : null\n}\n\n// SSR utilities for Next.js\nexport const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__'\n\nexport function addApolloState<P extends Record<string, unknown>>(\n client: LolClient,\n pageProps: { props: P }\n): { props: P & { [APOLLO_STATE_PROP_NAME]: NormalizedCacheObject } } {\n return {\n props: {\n ...pageProps.props,\n [APOLLO_STATE_PROP_NAME]: client.cache.extract(),\n },\n }\n}\n\nexport function initializeClientWithState<TApi extends ApiType>(\n config: LolClientConfig & { api: TApi },\n initialState?: NormalizedCacheObject\n): LolClient<TApi> {\n const client = createClient(config)\n\n if (initialState) {\n const existingCache = client.cache.extract()\n const mergedData = merge(existingCache, initialState, {\n arrayMerge: (dest, src) => [\n ...src,\n ...dest.filter((d) => src.every((s) => !deepEqual(d, s))),\n ],\n })\n client.cache.restore(mergedData)\n }\n\n return client\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b)\n}\n"]}
|