@timeback/powerpath 0.2.3-beta.20260331232130 → 0.2.3-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.
@@ -146,6 +146,17 @@ var TYPESCRIPT_RUNNER = {
146
146
  var patterns = null;
147
147
  var debugAll = false;
148
148
  var debugEnvSet = false;
149
+ function hasDebugOptIn() {
150
+ try {
151
+ const debugValue = process.env.DEBUG?.trim();
152
+ if (!debugValue) {
153
+ return false;
154
+ }
155
+ return debugValue.split(",").some((part) => part.trim().length > 0);
156
+ } catch {
157
+ return false;
158
+ }
159
+ }
149
160
  function patternToRegex(pattern) {
150
161
  const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
151
162
  const regexStr = escaped.replace(/\*/g, ".*");
@@ -155,7 +166,7 @@ function parseDebugEnv() {
155
166
  if (patterns !== null)
156
167
  return;
157
168
  patterns = [];
158
- if (typeof process === "undefined" || !process.env?.DEBUG) {
169
+ if (!hasDebugOptIn()) {
159
170
  debugEnvSet = false;
160
171
  return;
161
172
  }
@@ -377,6 +388,19 @@ var browserFormatter = (entry) => {
377
388
  };
378
389
  // ../../internal/logger/src/logger.ts
379
390
  var LOG_LEVELS = ["debug", "info", "warn", "error"];
391
+ var GLOBAL_LOGGING_CONFIG_KEY = Symbol.for("@timeback/internal-logger/config");
392
+ function shouldUseSilentFormatter() {
393
+ try {
394
+ return process.env["TIMEBACK_INTERNAL_LOGGER"] === "silent";
395
+ } catch {
396
+ return false;
397
+ }
398
+ }
399
+ function getGlobalLoggingConfig() {
400
+ const globalState = globalThis;
401
+ globalState[GLOBAL_LOGGING_CONFIG_KEY] ??= {};
402
+ return globalState[GLOBAL_LOGGING_CONFIG_KEY];
403
+ }
380
404
  function getFormatter(env) {
381
405
  switch (env) {
382
406
  case "terminal":
@@ -392,11 +416,14 @@ function getFormatter(env) {
392
416
  }
393
417
  }
394
418
  function getDefaultMinLevel() {
395
- if (typeof process !== "undefined" && process.env?.DEBUG) {
419
+ if (hasDebugOptIn()) {
396
420
  return "debug";
397
421
  }
398
422
  return "info";
399
423
  }
424
+ function getConfiguredFormatter(env, formatter) {
425
+ return formatter ?? getGlobalLoggingConfig().formatter ?? (shouldUseSilentFormatter() ? () => {} : getFormatter(env));
426
+ }
400
427
  function shouldLog(level, minLevel) {
401
428
  return LOG_LEVELS.indexOf(level) >= LOG_LEVELS.indexOf(minLevel);
402
429
  }
@@ -405,14 +432,14 @@ class Logger {
405
432
  scope;
406
433
  minLevel;
407
434
  environment;
408
- formatter;
435
+ explicitFormatter;
409
436
  defaultContext;
410
437
  constructor(options = {}) {
411
438
  this.scope = options.scope;
412
439
  this.minLevel = options.minLevel ?? getDefaultMinLevel();
413
440
  this.defaultContext = options.defaultContext ?? {};
414
441
  this.environment = options.environment ?? detectEnvironment();
415
- this.formatter = getFormatter(this.environment);
442
+ this.explicitFormatter = options.formatter;
416
443
  }
417
444
  child(scope) {
418
445
  const childScope = this.scope ? `${this.scope}:${scope}` : scope;
@@ -420,7 +447,8 @@ class Logger {
420
447
  scope: childScope,
421
448
  minLevel: this.minLevel,
422
449
  environment: this.environment,
423
- defaultContext: { ...this.defaultContext }
450
+ defaultContext: { ...this.defaultContext },
451
+ formatter: this.explicitFormatter
424
452
  });
425
453
  }
426
454
  withContext(context) {
@@ -428,7 +456,8 @@ class Logger {
428
456
  scope: this.scope,
429
457
  minLevel: this.minLevel,
430
458
  environment: this.environment,
431
- defaultContext: { ...this.defaultContext, ...context }
459
+ defaultContext: { ...this.defaultContext, ...context },
460
+ formatter: this.explicitFormatter
432
461
  });
433
462
  }
434
463
  debug(message, context) {
@@ -457,7 +486,7 @@ class Logger {
457
486
  context: context || Object.keys(this.defaultContext).length > 0 ? { ...this.defaultContext, ...context } : undefined,
458
487
  timestamp: new Date
459
488
  };
460
- this.formatter(entry);
489
+ getConfiguredFormatter(this.environment, this.explicitFormatter)(entry);
461
490
  }
462
491
  }
463
492
  function createLogger(options = {}) {
@@ -472,7 +501,6 @@ function isDebug() {
472
501
  return false;
473
502
  }
474
503
  }
475
- var log = createLogger({ scope: "auth", minLevel: isDebug() ? "debug" : "warn" });
476
504
 
477
505
  class TokenManager {
478
506
  config;
@@ -480,17 +508,22 @@ class TokenManager {
480
508
  tokenExpiry = 0;
481
509
  pendingRequest = null;
482
510
  fetchFn;
511
+ log;
483
512
  constructor(config) {
484
513
  this.config = config;
485
514
  this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
515
+ this.log = config.logger ?? createLogger({
516
+ scope: "auth",
517
+ minLevel: isDebug() ? "debug" : "warn"
518
+ });
486
519
  }
487
520
  async getToken() {
488
521
  if (this.accessToken && Date.now() < this.tokenExpiry) {
489
- log.debug("Using cached token");
522
+ this.log.debug("Using cached token");
490
523
  return this.accessToken;
491
524
  }
492
525
  if (this.pendingRequest) {
493
- log.debug("Waiting for in-flight token request");
526
+ this.log.debug("Waiting for in-flight token request");
494
527
  return this.pendingRequest;
495
528
  }
496
529
  this.pendingRequest = this.fetchToken();
@@ -501,7 +534,7 @@ class TokenManager {
501
534
  }
502
535
  }
503
536
  async fetchToken() {
504
- log.debug("Fetching new access token...");
537
+ this.log.debug("Fetching new access token...");
505
538
  const { clientId, clientSecret } = this.config.credentials;
506
539
  const credentials = btoa(`${clientId}:${clientSecret}`);
507
540
  const start = performance.now();
@@ -515,17 +548,17 @@ class TokenManager {
515
548
  });
516
549
  const duration = Math.round(performance.now() - start);
517
550
  if (!response.ok) {
518
- log.error(`Token request failed: ${response.status} ${response.statusText}`);
551
+ this.log.error(`Token request failed: ${response.status} ${response.statusText}`);
519
552
  throw new Error(`Failed to obtain access token: ${response.status} ${response.statusText}`);
520
553
  }
521
554
  const data = await response.json();
522
555
  this.accessToken = data.access_token;
523
556
  this.tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;
524
- log.debug(`Token acquired (${duration}ms, expires in ${data.expires_in}s)`);
557
+ this.log.debug(`Token acquired (${duration}ms, expires in ${data.expires_in}s)`);
525
558
  return this.accessToken;
526
559
  }
527
560
  invalidate() {
528
- log.debug("Token invalidated");
561
+ this.log.debug("Token invalidated");
529
562
  this.accessToken = null;
530
563
  this.tokenExpiry = 0;
531
564
  }
package/dist/errors.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  NotFoundError,
6
6
  UnauthorizedError,
7
7
  ValidationError
8
- } from "./chunk-setst1c6.js";
8
+ } from "./chunk-89bw8av5.js";
9
9
  import"./chunk-6jf1natv.js";
10
10
  export {
11
11
  ValidationError,
package/dist/index.d.ts CHANGED
@@ -3,37 +3,6 @@ export { AssignmentResult, Attempt, BulkResult, CourseProgressResponse, CreateAt
3
3
  import { CreateExternalPlacementTestInput, CreateExternalTestOutInput, CreateInternalTestInput, CreateNewAttemptInput, FinalStudentAssessmentResponseInput, GetAssessmentProgressParams, GetAttemptsParams, GetNextQuestionParams, ImportExternalTestAssignmentResultsParams, MakeExternalTestAssignmentInput, ResetAttemptInput, TestOutParams, UpdateStudentQuestionResponseInput, LessonPlansCreateInput, LessonPlanOperationsInput, LessonPlanUpdateStudentItemResponseInput, PlacementQueryParams, PlacementResetUserPlacementInput, RenderConfigUpsertInput, ScreeningResetSessionInput, ScreeningAssignTestInput, SyllabusQueryParams, TestAssignmentsListParams, TestAssignmentsCreateInput, TestAssignmentsUpdateInput, TestAssignmentsAdminParams, TestAssignmentsBulkInput, TestAssignmentsImportInput, MakeExternalStudentTestOutAssignmentInput } from '@timeback/types/zod';
4
4
  export { CreateExternalPlacementTestInput, CreateExternalTestOutInput, CreateInternalTestInput, CreateNewAttemptInput, FinalStudentAssessmentResponseInput, GetAssessmentProgressParams, GetAttemptsParams, GetNextQuestionParams, ImportExternalTestAssignmentResultsParams, LessonPlanOperationInput, LessonPlanOperationsInput, LessonPlanUpdateStudentItemResponseInput, LessonPlansCreateInput, MakeExternalStudentTestOutAssignmentInput, MakeExternalTestAssignmentInput, PlacementQueryParams, PlacementResetUserPlacementInput, ResetAttemptInput, ScreeningAssignTestInput, ScreeningResetSessionInput, SyllabusQueryParams, TestAssignmentsAdminParams, TestAssignmentsBulkInput, TestAssignmentsCreateInput, TestAssignmentsImportInput, TestAssignmentsListParams, TestAssignmentsUpdateInput, TestOutParams, UpdateStudentQuestionResponseInput } from '@timeback/types/zod';
5
5
 
6
- /**
7
- * Interface for obtaining OAuth2 access tokens.
8
- *
9
- * Implementations handle token caching and refresh automatically.
10
- */
11
- interface TokenProvider {
12
- /**
13
- * Get a valid access token.
14
- *
15
- * Returns a cached token if still valid, otherwise fetches a new one.
16
- *
17
- * @returns A valid access token string
18
- * @throws {Error} If token acquisition fails
19
- */
20
- getToken(): Promise<string>;
21
- /**
22
- * Invalidate the cached token.
23
- *
24
- * Forces the next getToken() call to fetch a fresh token.
25
- * Should be called when a request fails with 401 Unauthorized.
26
- *
27
- * Optional - not all implementations may support invalidation.
28
- */
29
- invalidate?(): void;
30
- }
31
-
32
- /**
33
- * All supported platforms.
34
- */
35
- declare const PLATFORMS: readonly ["BEYOND_AI", "LEARNWITH_AI"];
36
-
37
6
  /**
38
7
  * Type Definitions for `@timeback/internal-logger`
39
8
  *
@@ -69,6 +38,24 @@ type Environment$2 = 'terminal' | 'ci' | 'production' | 'browser' | 'test';
69
38
  * log.info('User created', { userId: 123, email: 'foo@bar.com' })
70
39
  */
71
40
  type LogContext = Record<string, unknown>;
41
+ /**
42
+ * A single log entry before it's formatted for output.
43
+ *
44
+ * This is the internal representation passed to formatters.
45
+ * Formatters transform this into environment-specific output.
46
+ */
47
+ interface LogEntry {
48
+ /** Severity level of this log entry */
49
+ level: LogLevel;
50
+ /** Human-readable log message */
51
+ message: string;
52
+ /** Optional namespace/category (e.g., "api", "db", "auth") */
53
+ scope?: string;
54
+ /** Optional structured data attached to this entry */
55
+ context?: LogContext;
56
+ /** When this log entry was created */
57
+ timestamp: Date;
58
+ }
72
59
  /**
73
60
  * Configuration options for creating a logger instance.
74
61
  */
@@ -94,7 +81,21 @@ interface LoggerOptions {
94
81
  * Useful for request IDs, user IDs, etc.
95
82
  */
96
83
  defaultContext?: LogContext;
84
+ /**
85
+ * Custom formatter override for this logger instance.
86
+ *
87
+ * When provided, this takes precedence over environment-based formatting.
88
+ * Useful for tests, custom sinks, or temporarily suppressing output.
89
+ */
90
+ formatter?: Formatter;
97
91
  }
92
+ /**
93
+ * Function that outputs a log entry in a specific format.
94
+ *
95
+ * Each environment has its own formatter. Formatters are responsible
96
+ * for the actual console.log/write calls.
97
+ */
98
+ type Formatter = (entry: LogEntry) => void;
98
99
 
99
100
  /**
100
101
  * Logger instance with environment-aware formatting.
@@ -109,8 +110,8 @@ declare class Logger {
109
110
  private minLevel;
110
111
  /** The detected or configured environment */
111
112
  private environment;
112
- /** Function that formats and outputs log entries */
113
- private formatter;
113
+ /** Optional explicit formatter override for this logger instance */
114
+ private explicitFormatter?;
114
115
  /** Context added to every log entry from this logger */
115
116
  private defaultContext;
116
117
  /**
@@ -200,6 +201,37 @@ declare class Logger {
200
201
  private log;
201
202
  }
202
203
 
204
+ /**
205
+ * Interface for obtaining OAuth2 access tokens.
206
+ *
207
+ * Implementations handle token caching and refresh automatically.
208
+ */
209
+ interface TokenProvider {
210
+ /**
211
+ * Get a valid access token.
212
+ *
213
+ * Returns a cached token if still valid, otherwise fetches a new one.
214
+ *
215
+ * @returns A valid access token string
216
+ * @throws {Error} If token acquisition fails
217
+ */
218
+ getToken(): Promise<string>;
219
+ /**
220
+ * Invalidate the cached token.
221
+ *
222
+ * Forces the next getToken() call to fetch a fresh token.
223
+ * Should be called when a request fails with 401 Unauthorized.
224
+ *
225
+ * Optional - not all implementations may support invalidation.
226
+ */
227
+ invalidate?(): void;
228
+ }
229
+
230
+ /**
231
+ * All supported platforms.
232
+ */
233
+ declare const PLATFORMS: readonly ["BEYOND_AI", "LEARNWITH_AI"];
234
+
203
235
  /**
204
236
  * Where Clause Types
205
237
  *
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  resolveToProvider,
9
9
  validateNonEmptyString,
10
10
  validateWithSchema
11
- } from "./chunk-setst1c6.js";
11
+ } from "./chunk-89bw8av5.js";
12
12
  import"./chunk-6jf1natv.js";
13
13
 
14
14
  // src/constants.ts
@@ -101,6 +101,13 @@ var StringTimebackGrade = z.string().transform((value, ctx) => {
101
101
  return z.NEVER;
102
102
  }
103
103
  const stripped = raw.replace(/\bgrade\b/g, "").replace(/(\d+)(st|nd|rd|th)\b/g, "$1").trim();
104
+ if (stripped === "") {
105
+ ctx.addIssue({
106
+ code: "custom",
107
+ message: "must be a valid Timeback grade"
108
+ });
109
+ return z.NEVER;
110
+ }
104
111
  if (stripped === "pre-k" || stripped === "pk") {
105
112
  return -1;
106
113
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timeback/powerpath",
3
- "version": "0.2.3-beta.20260331232130",
3
+ "version": "0.2.3-beta.20260403024308",
4
4
  "description": "PowerPath client SDK for Timeback",
5
5
  "type": "module",
6
6
  "exports": {