@timeback/oneroster 0.2.2-beta.20260401223329 → 0.2.2-beta.20260403024308
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/{chunk-bnh0e9yt.js → chunk-482xgqsm.js} +47 -14
- package/dist/errors.js +1 -1
- package/dist/index.d.ts +65 -33
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -218,6 +218,17 @@ var TYPESCRIPT_RUNNER = {
|
|
|
218
218
|
var patterns = null;
|
|
219
219
|
var debugAll = false;
|
|
220
220
|
var debugEnvSet = false;
|
|
221
|
+
function hasDebugOptIn() {
|
|
222
|
+
try {
|
|
223
|
+
const debugValue = process.env.DEBUG?.trim();
|
|
224
|
+
if (!debugValue) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
return debugValue.split(",").some((part) => part.trim().length > 0);
|
|
228
|
+
} catch {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
221
232
|
function patternToRegex(pattern) {
|
|
222
233
|
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
223
234
|
const regexStr = escaped.replace(/\*/g, ".*");
|
|
@@ -227,7 +238,7 @@ function parseDebugEnv() {
|
|
|
227
238
|
if (patterns !== null)
|
|
228
239
|
return;
|
|
229
240
|
patterns = [];
|
|
230
|
-
if (
|
|
241
|
+
if (!hasDebugOptIn()) {
|
|
231
242
|
debugEnvSet = false;
|
|
232
243
|
return;
|
|
233
244
|
}
|
|
@@ -449,6 +460,19 @@ var browserFormatter = (entry) => {
|
|
|
449
460
|
};
|
|
450
461
|
// ../../internal/logger/src/logger.ts
|
|
451
462
|
var LOG_LEVELS = ["debug", "info", "warn", "error"];
|
|
463
|
+
var GLOBAL_LOGGING_CONFIG_KEY = Symbol.for("@timeback/internal-logger/config");
|
|
464
|
+
function shouldUseSilentFormatter() {
|
|
465
|
+
try {
|
|
466
|
+
return process.env["TIMEBACK_INTERNAL_LOGGER"] === "silent";
|
|
467
|
+
} catch {
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
function getGlobalLoggingConfig() {
|
|
472
|
+
const globalState = globalThis;
|
|
473
|
+
globalState[GLOBAL_LOGGING_CONFIG_KEY] ??= {};
|
|
474
|
+
return globalState[GLOBAL_LOGGING_CONFIG_KEY];
|
|
475
|
+
}
|
|
452
476
|
function getFormatter(env) {
|
|
453
477
|
switch (env) {
|
|
454
478
|
case "terminal":
|
|
@@ -464,11 +488,14 @@ function getFormatter(env) {
|
|
|
464
488
|
}
|
|
465
489
|
}
|
|
466
490
|
function getDefaultMinLevel() {
|
|
467
|
-
if (
|
|
491
|
+
if (hasDebugOptIn()) {
|
|
468
492
|
return "debug";
|
|
469
493
|
}
|
|
470
494
|
return "info";
|
|
471
495
|
}
|
|
496
|
+
function getConfiguredFormatter(env, formatter) {
|
|
497
|
+
return formatter ?? getGlobalLoggingConfig().formatter ?? (shouldUseSilentFormatter() ? () => {} : getFormatter(env));
|
|
498
|
+
}
|
|
472
499
|
function shouldLog(level, minLevel) {
|
|
473
500
|
return LOG_LEVELS.indexOf(level) >= LOG_LEVELS.indexOf(minLevel);
|
|
474
501
|
}
|
|
@@ -477,14 +504,14 @@ class Logger {
|
|
|
477
504
|
scope;
|
|
478
505
|
minLevel;
|
|
479
506
|
environment;
|
|
480
|
-
|
|
507
|
+
explicitFormatter;
|
|
481
508
|
defaultContext;
|
|
482
509
|
constructor(options = {}) {
|
|
483
510
|
this.scope = options.scope;
|
|
484
511
|
this.minLevel = options.minLevel ?? getDefaultMinLevel();
|
|
485
512
|
this.defaultContext = options.defaultContext ?? {};
|
|
486
513
|
this.environment = options.environment ?? detectEnvironment();
|
|
487
|
-
this.
|
|
514
|
+
this.explicitFormatter = options.formatter;
|
|
488
515
|
}
|
|
489
516
|
child(scope) {
|
|
490
517
|
const childScope = this.scope ? `${this.scope}:${scope}` : scope;
|
|
@@ -492,7 +519,8 @@ class Logger {
|
|
|
492
519
|
scope: childScope,
|
|
493
520
|
minLevel: this.minLevel,
|
|
494
521
|
environment: this.environment,
|
|
495
|
-
defaultContext: { ...this.defaultContext }
|
|
522
|
+
defaultContext: { ...this.defaultContext },
|
|
523
|
+
formatter: this.explicitFormatter
|
|
496
524
|
});
|
|
497
525
|
}
|
|
498
526
|
withContext(context) {
|
|
@@ -500,7 +528,8 @@ class Logger {
|
|
|
500
528
|
scope: this.scope,
|
|
501
529
|
minLevel: this.minLevel,
|
|
502
530
|
environment: this.environment,
|
|
503
|
-
defaultContext: { ...this.defaultContext, ...context }
|
|
531
|
+
defaultContext: { ...this.defaultContext, ...context },
|
|
532
|
+
formatter: this.explicitFormatter
|
|
504
533
|
});
|
|
505
534
|
}
|
|
506
535
|
debug(message, context) {
|
|
@@ -529,7 +558,7 @@ class Logger {
|
|
|
529
558
|
context: context || Object.keys(this.defaultContext).length > 0 ? { ...this.defaultContext, ...context } : undefined,
|
|
530
559
|
timestamp: new Date
|
|
531
560
|
};
|
|
532
|
-
this.
|
|
561
|
+
getConfiguredFormatter(this.environment, this.explicitFormatter)(entry);
|
|
533
562
|
}
|
|
534
563
|
}
|
|
535
564
|
function createLogger(options = {}) {
|
|
@@ -544,7 +573,6 @@ function isDebug() {
|
|
|
544
573
|
return false;
|
|
545
574
|
}
|
|
546
575
|
}
|
|
547
|
-
var log = createLogger({ scope: "auth", minLevel: isDebug() ? "debug" : "warn" });
|
|
548
576
|
|
|
549
577
|
class TokenManager {
|
|
550
578
|
config;
|
|
@@ -552,17 +580,22 @@ class TokenManager {
|
|
|
552
580
|
tokenExpiry = 0;
|
|
553
581
|
pendingRequest = null;
|
|
554
582
|
fetchFn;
|
|
583
|
+
log;
|
|
555
584
|
constructor(config) {
|
|
556
585
|
this.config = config;
|
|
557
586
|
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
587
|
+
this.log = config.logger ?? createLogger({
|
|
588
|
+
scope: "auth",
|
|
589
|
+
minLevel: isDebug() ? "debug" : "warn"
|
|
590
|
+
});
|
|
558
591
|
}
|
|
559
592
|
async getToken() {
|
|
560
593
|
if (this.accessToken && Date.now() < this.tokenExpiry) {
|
|
561
|
-
log.debug("Using cached token");
|
|
594
|
+
this.log.debug("Using cached token");
|
|
562
595
|
return this.accessToken;
|
|
563
596
|
}
|
|
564
597
|
if (this.pendingRequest) {
|
|
565
|
-
log.debug("Waiting for in-flight token request");
|
|
598
|
+
this.log.debug("Waiting for in-flight token request");
|
|
566
599
|
return this.pendingRequest;
|
|
567
600
|
}
|
|
568
601
|
this.pendingRequest = this.fetchToken();
|
|
@@ -573,7 +606,7 @@ class TokenManager {
|
|
|
573
606
|
}
|
|
574
607
|
}
|
|
575
608
|
async fetchToken() {
|
|
576
|
-
log.debug("Fetching new access token...");
|
|
609
|
+
this.log.debug("Fetching new access token...");
|
|
577
610
|
const { clientId, clientSecret } = this.config.credentials;
|
|
578
611
|
const credentials = btoa(`${clientId}:${clientSecret}`);
|
|
579
612
|
const start = performance.now();
|
|
@@ -587,17 +620,17 @@ class TokenManager {
|
|
|
587
620
|
});
|
|
588
621
|
const duration = Math.round(performance.now() - start);
|
|
589
622
|
if (!response.ok) {
|
|
590
|
-
log.error(`Token request failed: ${response.status} ${response.statusText}`);
|
|
623
|
+
this.log.error(`Token request failed: ${response.status} ${response.statusText}`);
|
|
591
624
|
throw new Error(`Failed to obtain access token: ${response.status} ${response.statusText}`);
|
|
592
625
|
}
|
|
593
626
|
const data = await response.json();
|
|
594
627
|
this.accessToken = data.access_token;
|
|
595
628
|
this.tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;
|
|
596
|
-
log.debug(`Token acquired (${duration}ms, expires in ${data.expires_in}s)`);
|
|
629
|
+
this.log.debug(`Token acquired (${duration}ms, expires in ${data.expires_in}s)`);
|
|
597
630
|
return this.accessToken;
|
|
598
631
|
}
|
|
599
632
|
invalidate() {
|
|
600
|
-
log.debug("Token invalidated");
|
|
633
|
+
this.log.debug("Token invalidated");
|
|
601
634
|
this.accessToken = null;
|
|
602
635
|
this.tokenExpiry = 0;
|
|
603
636
|
}
|
package/dist/errors.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -2,37 +2,6 @@ import { AcademicSessionCreateInput, EnrollInput, LineItemCreateInput, ResultCre
|
|
|
2
2
|
import { LineItem, Result, CreateResponse, Resource, Base, ResourceType, AcademicSession, AcademicSessionFilterFields, ClassFilterFields, Class, GradingPeriod, UserFilterFields, User, LineItemFilterFields, ResultFilterFields, ResourceFilterFields, ScoreScaleFilterFields, ScoreScale, CategoryFilterFields, Category, Course, CourseComponentFilterFields, CourseComponent, Organization, EnrollmentFilterFields, Enrollment, CourseFilterFields, CredentialCreateResponse, DecryptedCredential, OrganizationFilterFields, ComponentResourceFilterFields, ComponentResource, AssessmentLineItem, AssessmentLineItemFilterFields, AssessmentResult, AssessmentResultFilterFields, Demographics, DemographicsFilterFields } from '@timeback/types/protocols/oneroster';
|
|
3
3
|
import { z } from 'zod/v4';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Interface for obtaining OAuth2 access tokens.
|
|
7
|
-
*
|
|
8
|
-
* Implementations handle token caching and refresh automatically.
|
|
9
|
-
*/
|
|
10
|
-
interface TokenProvider {
|
|
11
|
-
/**
|
|
12
|
-
* Get a valid access token.
|
|
13
|
-
*
|
|
14
|
-
* Returns a cached token if still valid, otherwise fetches a new one.
|
|
15
|
-
*
|
|
16
|
-
* @returns A valid access token string
|
|
17
|
-
* @throws {Error} If token acquisition fails
|
|
18
|
-
*/
|
|
19
|
-
getToken(): Promise<string>;
|
|
20
|
-
/**
|
|
21
|
-
* Invalidate the cached token.
|
|
22
|
-
*
|
|
23
|
-
* Forces the next getToken() call to fetch a fresh token.
|
|
24
|
-
* Should be called when a request fails with 401 Unauthorized.
|
|
25
|
-
*
|
|
26
|
-
* Optional - not all implementations may support invalidation.
|
|
27
|
-
*/
|
|
28
|
-
invalidate?(): void;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* All supported platforms.
|
|
33
|
-
*/
|
|
34
|
-
declare const PLATFORMS: readonly ["BEYOND_AI", "LEARNWITH_AI"];
|
|
35
|
-
|
|
36
5
|
/**
|
|
37
6
|
* Type Definitions for `@timeback/internal-logger`
|
|
38
7
|
*
|
|
@@ -68,6 +37,24 @@ type Environment$2 = 'terminal' | 'ci' | 'production' | 'browser' | 'test';
|
|
|
68
37
|
* log.info('User created', { userId: 123, email: 'foo@bar.com' })
|
|
69
38
|
*/
|
|
70
39
|
type LogContext = Record<string, unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* A single log entry before it's formatted for output.
|
|
42
|
+
*
|
|
43
|
+
* This is the internal representation passed to formatters.
|
|
44
|
+
* Formatters transform this into environment-specific output.
|
|
45
|
+
*/
|
|
46
|
+
interface LogEntry {
|
|
47
|
+
/** Severity level of this log entry */
|
|
48
|
+
level: LogLevel;
|
|
49
|
+
/** Human-readable log message */
|
|
50
|
+
message: string;
|
|
51
|
+
/** Optional namespace/category (e.g., "api", "db", "auth") */
|
|
52
|
+
scope?: string;
|
|
53
|
+
/** Optional structured data attached to this entry */
|
|
54
|
+
context?: LogContext;
|
|
55
|
+
/** When this log entry was created */
|
|
56
|
+
timestamp: Date;
|
|
57
|
+
}
|
|
71
58
|
/**
|
|
72
59
|
* Configuration options for creating a logger instance.
|
|
73
60
|
*/
|
|
@@ -93,7 +80,21 @@ interface LoggerOptions {
|
|
|
93
80
|
* Useful for request IDs, user IDs, etc.
|
|
94
81
|
*/
|
|
95
82
|
defaultContext?: LogContext;
|
|
83
|
+
/**
|
|
84
|
+
* Custom formatter override for this logger instance.
|
|
85
|
+
*
|
|
86
|
+
* When provided, this takes precedence over environment-based formatting.
|
|
87
|
+
* Useful for tests, custom sinks, or temporarily suppressing output.
|
|
88
|
+
*/
|
|
89
|
+
formatter?: Formatter;
|
|
96
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Function that outputs a log entry in a specific format.
|
|
93
|
+
*
|
|
94
|
+
* Each environment has its own formatter. Formatters are responsible
|
|
95
|
+
* for the actual console.log/write calls.
|
|
96
|
+
*/
|
|
97
|
+
type Formatter = (entry: LogEntry) => void;
|
|
97
98
|
|
|
98
99
|
/**
|
|
99
100
|
* Logger instance with environment-aware formatting.
|
|
@@ -108,8 +109,8 @@ declare class Logger {
|
|
|
108
109
|
private minLevel;
|
|
109
110
|
/** The detected or configured environment */
|
|
110
111
|
private environment;
|
|
111
|
-
/**
|
|
112
|
-
private
|
|
112
|
+
/** Optional explicit formatter override for this logger instance */
|
|
113
|
+
private explicitFormatter?;
|
|
113
114
|
/** Context added to every log entry from this logger */
|
|
114
115
|
private defaultContext;
|
|
115
116
|
/**
|
|
@@ -199,6 +200,37 @@ declare class Logger {
|
|
|
199
200
|
private log;
|
|
200
201
|
}
|
|
201
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Interface for obtaining OAuth2 access tokens.
|
|
205
|
+
*
|
|
206
|
+
* Implementations handle token caching and refresh automatically.
|
|
207
|
+
*/
|
|
208
|
+
interface TokenProvider {
|
|
209
|
+
/**
|
|
210
|
+
* Get a valid access token.
|
|
211
|
+
*
|
|
212
|
+
* Returns a cached token if still valid, otherwise fetches a new one.
|
|
213
|
+
*
|
|
214
|
+
* @returns A valid access token string
|
|
215
|
+
* @throws {Error} If token acquisition fails
|
|
216
|
+
*/
|
|
217
|
+
getToken(): Promise<string>;
|
|
218
|
+
/**
|
|
219
|
+
* Invalidate the cached token.
|
|
220
|
+
*
|
|
221
|
+
* Forces the next getToken() call to fetch a fresh token.
|
|
222
|
+
* Should be called when a request fails with 401 Unauthorized.
|
|
223
|
+
*
|
|
224
|
+
* Optional - not all implementations may support invalidation.
|
|
225
|
+
*/
|
|
226
|
+
invalidate?(): void;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* All supported platforms.
|
|
231
|
+
*/
|
|
232
|
+
declare const PLATFORMS: readonly ["BEYOND_AI", "LEARNWITH_AI"];
|
|
233
|
+
|
|
202
234
|
/**
|
|
203
235
|
* Where Clause Types
|
|
204
236
|
*
|
package/dist/index.js
CHANGED