@timeback/oneroster 0.2.2-beta.20260401223329 → 0.2.2-beta.20260409195426

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.
@@ -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 (typeof process === "undefined" || !process.env?.DEBUG) {
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 (typeof process !== "undefined" && process.env?.DEBUG) {
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
- formatter;
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.formatter = getFormatter(this.environment);
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.formatter(entry);
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
@@ -5,7 +5,7 @@ import {
5
5
  NotFoundError,
6
6
  UnauthorizedError,
7
7
  ValidationError
8
- } from "./chunk-bnh0e9yt.js";
8
+ } from "./chunk-482xgqsm.js";
9
9
  import"./chunk-6jf1natv.js";
10
10
  export {
11
11
  ValidationError,
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
- /** Function that formats and outputs log entries */
112
- private formatter;
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
@@ -12,7 +12,7 @@ import {
12
12
  validateSourcedId,
13
13
  validateWithSchema,
14
14
  whereToFilter
15
- } from "./chunk-bnh0e9yt.js";
15
+ } from "./chunk-482xgqsm.js";
16
16
  import"./chunk-6jf1natv.js";
17
17
 
18
18
  // src/constants.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timeback/oneroster",
3
- "version": "0.2.2-beta.20260401223329",
3
+ "version": "0.2.2-beta.20260409195426",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -41,6 +41,6 @@
41
41
  "esbuild": "^0.27.3"
42
42
  },
43
43
  "peerDependencies": {
44
- "typescript": "^5"
44
+ "typescript": "^5 || ^6"
45
45
  }
46
46
  }