@gyldendalas/gyldendal-divine-api 1.2.0 → 2.0.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/index.cjs +0 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -879
- package/dist/index.d.mts +1 -879
- package/dist/index.mjs +1 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -450,14 +450,6 @@ var TaggingService = class extends BaseService {
|
|
|
450
450
|
};
|
|
451
451
|
//#endregion
|
|
452
452
|
//#region src/services/polly_service.ts
|
|
453
|
-
let SSMLSpeechSpeeds = /* @__PURE__ */ function(SSMLSpeechSpeeds) {
|
|
454
|
-
SSMLSpeechSpeeds[SSMLSpeechSpeeds["X_SLOW"] = 1] = "X_SLOW";
|
|
455
|
-
SSMLSpeechSpeeds[SSMLSpeechSpeeds["SLOW"] = 2] = "SLOW";
|
|
456
|
-
SSMLSpeechSpeeds[SSMLSpeechSpeeds["MEDIUM"] = 3] = "MEDIUM";
|
|
457
|
-
SSMLSpeechSpeeds[SSMLSpeechSpeeds["FAST"] = 4] = "FAST";
|
|
458
|
-
SSMLSpeechSpeeds[SSMLSpeechSpeeds["X_FAST"] = 5] = "X_FAST";
|
|
459
|
-
return SSMLSpeechSpeeds;
|
|
460
|
-
}({});
|
|
461
453
|
var PollyService = class extends BaseService {
|
|
462
454
|
serviceName = "polly";
|
|
463
455
|
async synthesize({ body, timeout = 3e3 }) {
|
|
@@ -491,11 +483,6 @@ var CookieConsentLog = class extends BaseService {
|
|
|
491
483
|
};
|
|
492
484
|
//#endregion
|
|
493
485
|
//#region src/services/highlight_service.ts
|
|
494
|
-
let HighlightResultType = /* @__PURE__ */ function(HighlightResultType) {
|
|
495
|
-
HighlightResultType["highlight"] = "highlight";
|
|
496
|
-
HighlightResultType["note"] = "note";
|
|
497
|
-
return HighlightResultType;
|
|
498
|
-
}({});
|
|
499
486
|
var HighlightService = class extends BaseService {
|
|
500
487
|
serviceName = "highlight";
|
|
501
488
|
async search({ search, timeout = 3e3 }) {
|
|
@@ -1420,13 +1407,11 @@ exports.AIBotService = AIBotService;
|
|
|
1420
1407
|
exports.CookieConsentLog = CookieConsentLog;
|
|
1421
1408
|
exports.ENVIRONMENTS = ENVIRONMENTS;
|
|
1422
1409
|
exports.GALE_QA_URL = GALE_QA_URL;
|
|
1423
|
-
exports.HighlightResultType = HighlightResultType;
|
|
1424
1410
|
exports.HighlightService = HighlightService;
|
|
1425
1411
|
exports.PdfGeneratorService = PdfGeneratorService;
|
|
1426
1412
|
exports.PollyService = PollyService;
|
|
1427
1413
|
exports.QuizService = QuizService;
|
|
1428
1414
|
exports.SERVICE_URLS = SERVICE_URLS;
|
|
1429
|
-
exports.SSMLSpeechSpeeds = SSMLSpeechSpeeds;
|
|
1430
1415
|
exports.SolrProxyService = SolrProxyService;
|
|
1431
1416
|
exports.TaggingService = TaggingService;
|
|
1432
1417
|
exports.UserFolders = UserFolders;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["uuidv4"],"sources":["../src/jwt.ts","../src/services/service_urls.ts","../src/services/service_overrides.ts","../src/services/base_service.ts","../src/services/tagging_service.ts","../src/services/polly_service.ts","../src/services/cookie_consent_log.ts","../src/services/highlight_service.ts","../src/services/user_settings_base.ts","../src/services/user_settings_clientsettings.ts","../src/services/user_settings_bookmarks.ts","../src/services/user_settings_continue.ts","../src/services/user_settings_mru.ts","../src/services/pdf_generator.ts","../src/services/highlevel/tagging/user_folders.ts","../src/services/ai_bot_service.ts","../src/services/quiz_service.ts","../src/services/writing_task_service.ts","../src/services/solr_proxy_service.ts"],"sourcesContent":["// ECMAScript maximum Date time value in milliseconds: ±100 million days from epoch.\n// new Date() silently returns Invalid Date for values outside this range.\nconst MAX_DATE_MS = 8_640_000_000_000_000;\n\n/**\n * Decodes a base64url-encoded JWT segment (RFC 4648 §5).\n */\nfunction decodeBase64Url(segment: string): string {\n const base64 = segment.replace(/-/g, '+').replace(/_/g, '/');\n // Restore padding to a multiple of 4\n const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');\n try {\n return atob(padded);\n } catch {\n throw new Error('JWT payload segment is not valid base64url');\n }\n}\n\n/**\n * Extracts the expiry time from a JWT token's `exp` claim.\n *\n * The `exp` claim is a NumericDate (Unix timestamp in seconds, per RFC 7519).\n */\nexport function getJwtExpiry(token: string): Date {\n const payload = extractJWTPayload(token);\n if (!('exp' in payload)) {\n throw new Error('Invalid JWT: payload does not contain an \"exp\" claim');\n }\n\n const exp = (payload as Record<string, unknown>).exp;\n\n if (typeof exp !== 'number') {\n throw new Error(\n `Invalid JWT: \"exp\" claim must be a number, got ${typeof exp}`\n );\n }\n\n if (!Number.isFinite(exp)) {\n throw new Error(`Invalid JWT: \"exp\" claim is not a finite number`);\n }\n\n // JWT NumericDate is seconds since epoch; Date constructor takes milliseconds.\n const expMs = exp * 1000;\n if (expMs < -MAX_DATE_MS || expMs > MAX_DATE_MS) {\n throw new Error(\n `Invalid JWT: \"exp\" value (${exp}) is outside the valid JavaScript Date range`\n );\n }\n\n return new Date(expMs);\n}\n\nfunction extractJWTPayload(token: string): Record<string, unknown> {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error(\n `Invalid JWT: expected 3 dot-separated segments, got ${parts.length}`\n );\n }\n const payloadSegment = parts[1];\n if (payloadSegment.length === 0) {\n throw new Error('Invalid JWT: payload segment is empty');\n }\n const decoded = decodeBase64Url(payloadSegment);\n let payload: unknown;\n try {\n payload = JSON.parse(decoded);\n } catch {\n throw new Error('Invalid JWT: payload is not valid JSON');\n }\n if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {\n throw new Error('Invalid JWT: payload must be a JSON object');\n }\n return payload as Record<string, unknown>;\n}\n","/**\n * The `installationpurpose` values a caller may pass as `environment`, which\n * is more values than there are places to point them at.\n */\nexport const ENVIRONMENTS = [\n 'production',\n 'development',\n 'testing',\n 'local',\n 'test'\n] as const;\n\nexport type ServiceEnvironment = (typeof ENVIRONMENTS)[number];\n\nexport function isServiceEnvironment(\n value: string\n): value is ServiceEnvironment {\n return (ENVIRONMENTS as readonly string[]).includes(value);\n}\n\n/**\n * The four places a service actually runs. Several environments share one:\n * `development` and `testing` both mean staging, and having them collapse\n * here rather than in ten separate switches is what stops one of them\n * quietly drifting away from the other.\n */\ntype Target = 'production' | 'staging' | 'local' | 'mock';\n\nconst TARGETS: Record<ServiceEnvironment, Target> = {\n production: 'production',\n development: 'staging',\n testing: 'staging',\n local: 'local',\n test: 'mock'\n};\n\n/**\n * A service's four addresses. `baseDomain` is the TYPO3 installation's domain\n * and only the hosted environments use it; local ports and the mock server\n * are the same wherever the caller runs.\n */\ntype ServiceLocations = Record<Target, (baseDomain: string) => string>;\n\n/**\n * The hosted hostnames are written out rather than derived from the service\n * name: `solr-proxy-staging.eu-west-1`, `ai-bot-service-staging.eu-west-1`\n * and the whole of `quiz` already break whatever pattern one would derive,\n * and a wrong host is worth more than the repetition costs.\n *\n * The local ports are the reserved 4110-4180 block documented in the README.\n */\nexport const SERVICE_URLS = {\n userSettings: {\n production: (d) => `https://user-settings-service.services.${d}`,\n staging: (d) => `https://staging-user-settings-service.services.${d}`,\n local: () => 'http://127.0.0.1:4110',\n mock: () => 'https://localhost:3010/services/usersettingsservice'\n },\n highlight: {\n production: (d) => `https://highlights.services.${d}`,\n staging: (d) => `https://staging-highlights.services.${d}`,\n local: () => 'http://127.0.0.1:4120',\n mock: () => 'https://localhost:3010/services/highlight'\n },\n pdfGenerator: {\n production: (d) => `https://pdfgenerator.services.${d}`,\n staging: (d) => `https://staging-pdfgenerator.services.${d}`,\n local: () => 'http://127.0.0.1:4130',\n mock: () => 'https://localhost:3010/services/pdfgenerator'\n },\n writingTask: {\n production: (d) => `https://writingtask.services.${d}`,\n staging: (d) => `https://staging-writingtask.services.${d}`,\n local: () => 'http://127.0.0.1:4140',\n mock: () => 'https://localhost:3010/services/writingtask'\n },\n solrProxy: {\n production: (d) => `https://solr-proxy.eu-west-1.${d}`,\n staging: (d) => `https://solr-proxy-staging.eu-west-1.${d}`,\n local: () => 'http://127.0.0.1:4150',\n mock: () => 'https://localhost:3010/services/solrproxy'\n },\n tagging: {\n production: (d) => `https://tagging.services.${d}`,\n staging: (d) => `https://staging-tagging.services.${d}`,\n local: () => 'http://127.0.0.1:4160',\n mock: () => 'https://localhost:3010/services/tagging'\n },\n aiBot: {\n production: (d) => `https://ai-bot-service.eu-west-1.${d}`,\n staging: (d) => `https://ai-bot-service-staging.eu-west-1.${d}`,\n local: () => 'http://127.0.0.1:4170',\n mock: () => 'https://localhost:3010/services/aibotservice'\n },\n cookieConsentLog: {\n production: (d) => `https://cookieconsentlog.services.${d}`,\n staging: (d) => `https://staging-cookieconsentlog.services.${d}`,\n local: () => 'http://127.0.0.1:4180',\n mock: () => 'https://localhost:3010/services/cookieconsentlog'\n },\n polly: {\n // Its container port 3000 is taken by nuxt dev, hence 3200 rather than a\n // port from the reserved block.\n production: (d) => `https://appear-polly.services.${d}`,\n staging: (d) => `https://staging-appear-polly.services.${d}`,\n local: () => 'http://127.0.0.1:3200',\n mock: () => 'https://localhost:3010/services/polly'\n },\n quiz: {\n // Gale has no local instance, so `local` shares the staging one.\n production: () => 'https://api.iquiz.dk/api',\n staging: () => 'https://galecms.test.tibalo.dk/api',\n local: () => 'https://galecms.test.tibalo.dk/api',\n mock: () => 'https://localhost:3010/galeapi/api'\n }\n} as const satisfies Record<string, ServiceLocations>;\n\nexport type ServiceName = keyof typeof SERVICE_URLS;\n\n/**\n * Gale CMS's QA installation, which is not a target of its own: `quiz` is the\n * only service with a QA endpoint, and a fifth `Target` would oblige the other\n * nine to name one they do not have.\n *\n * It is reached by overriding `quiz` with it, so the URL stays in this file\n * and a caller who turns it on keeps tracking this package:\n *\n * ```ts\n * environmentOverrides: { quiz: GALE_QA_URL }\n * ```\n *\n * TYPO3 asks for it through `site.sso.sso_overrides.galeQaEndpointEnabled`,\n * which is a testing arrangement: honour it outside production only.\n */\nexport const GALE_QA_URL = 'https://galecms.qa.tibalo.dk/api';\n\n/** Where `service` answers in `environment`. */\nexport function resolveServiceUrl(\n service: ServiceName,\n environment: string,\n baseDomain: string\n): string {\n if (!isServiceEnvironment(environment)) {\n throw new Error(`Unknown environment: ${environment}`);\n }\n return SERVICE_URLS[service][TARGETS[environment]](baseDomain);\n}\n","/**\n * Pointing one service somewhere else than the rest.\n *\n * A caller developing locally usually wants most services from staging and\n * one from their own machine. The override says which *environment* that one\n * service resolves in, not which URL it answers on, so the caller keeps\n * tracking `service_urls.ts` for every service they did not name — and for\n * the named one too, whenever its local port moves.\n *\n * A URL is still accepted for the cases the table cannot know about (a\n * service on a non-standard port, a tunnel, a colleague's branch deploy).\n *\n * Every override is reported, because the failure mode of all of this is a\n * forgotten one: an `environmentOverrides` entry that reached a release, or\n * an environment variable exported three weeks ago.\n */\n\nimport {\n ENVIRONMENTS,\n type ServiceEnvironment,\n type ServiceName\n} from './service_urls.js';\n\n/**\n * An environment name, or a URL for the endpoints the table cannot know\n * about. The union is written this way so an editor still suggests the\n * environment names while accepting a URL alongside them.\n */\nexport type ServiceOverride = ServiceEnvironment | (string & {});\n\nexport type EnvironmentOverrides = Partial<\n Record<ServiceName, ServiceOverride>\n>;\n\n/**\n * Where an override came from. Reporting it is most of the value: \"highlight\n * is on 127.0.0.1\" is a puzzle on its own, and stops being one as soon as it\n * says which knob did it.\n */\nexport type OverrideSource =\n | 'serviceUrl'\n | 'environmentOverrides'\n | 'env'\n | 'globalThis';\n\nexport interface OverrideDetails {\n service: ServiceName;\n /** The environment the service would have resolved in otherwise. */\n environment: string;\n /** The URL it resolved to instead. */\n resolved: string;\n source: OverrideSource;\n /** The one-line form the default reporter writes to the console. */\n message: string;\n}\n\nexport type OverrideReporter = (details: OverrideDetails) => void;\n\n/**\n * Set by a dev-only Nuxt plugin or an injected script, and the only way to\n * reach the browser bundle, where there is no `process.env`.\n */\nconst GLOBAL_OVERRIDES_KEY = '__divineEnvironmentOverrides';\n\n/** `pdfGenerator` is configured as `DIVINE_ENV_PDF_GENERATOR`. */\nexport function overrideEnvVarName(service: ServiceName): string {\n return `DIVINE_ENV_${service.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase()}`;\n}\n\n/**\n * An override the developer's machine carries rather than the application's\n * code. `process.env` is read through a computed key so a bundler treats it\n * as a lookup rather than inlining a build-time value, and both accesses are\n * guarded because neither global exists everywhere this package runs.\n *\n * The environment variable wins: it is set per run of the application, so it\n * is the more deliberate of the two.\n */\nexport function ambientOverride(\n service: ServiceName\n): { value: string; source: OverrideSource } | undefined {\n const fromEnv =\n typeof process !== 'undefined' && process.env\n ? process.env[overrideEnvVarName(service)]\n : undefined;\n if (fromEnv) {\n return { value: fromEnv, source: 'env' };\n }\n\n const fromGlobal = (\n globalThis as Record<string, unknown> as {\n [GLOBAL_OVERRIDES_KEY]?: EnvironmentOverrides;\n }\n )[GLOBAL_OVERRIDES_KEY]?.[service];\n if (fromGlobal) {\n return { value: fromGlobal, source: 'globalThis' };\n }\n\n return undefined;\n}\n\n/** An override that is not an environment name has to be a URL we can call. */\nexport function overrideToUrl(\n value: string,\n service: ServiceName,\n source: OverrideSource\n): string {\n if (/^https?:\\/\\//.test(value)) {\n return value;\n }\n throw new Error(\n `Invalid ${source} override for ${service}: \"${value}\" is neither an environment (${ENVIRONMENTS.join(', ')}) nor an http(s) URL.`\n );\n}\n\n/**\n * Already-reported overrides, so a warning survives being read.\n * `getUrlPrefix()` runs on every request, and an override that warns on every\n * one of them is an override nobody reads.\n *\n * This is process-wide mutable state, which is exactly what a per-request\n * `environment` must never be kept in — but it only ever suppresses output,\n * and \"once per process\" is the cadence a server operator wants anyway.\n */\nconst reported = new Set<string>();\n\n/** Test seam: forget what has already been reported. */\nexport function resetOverrideReports(): void {\n reported.clear();\n}\n\nconst defaultReporter: OverrideReporter = (details) =>\n console.warn(details.message);\n\n/**\n * Report an override the first time it resolves. Deliberately not silenced in\n * production: an `environmentOverrides` entry that reached a release is the\n * single thing this is here to catch.\n */\nexport function reportOverride(\n {\n service,\n environment,\n resolved,\n source\n }: Omit<OverrideDetails, 'message'>,\n onOverride?: OverrideReporter\n): void {\n const key = `${source}:${service}:${resolved}`;\n if (reported.has(key)) {\n return;\n }\n reported.add(key);\n\n const message =\n `[gyldendal-divine-api] ${service} is overridden: resolved to ${resolved} ` +\n `instead of its \"${environment}\" endpoint (source: ${source}).`;\n\n (onOverride ?? defaultReporter)({\n service,\n environment,\n resolved,\n source,\n message\n });\n}\n","import {\n ambientOverride,\n overrideToUrl,\n reportOverride,\n type EnvironmentOverrides,\n type OverrideReporter,\n type OverrideSource\n} from './service_overrides.js';\nimport {\n isServiceEnvironment,\n resolveServiceUrl,\n type ServiceName\n} from './service_urls.js';\n\nexport class HTTPError extends Error {\n public response: Response;\n\n constructor(message: string, response: Response) {\n super();\n this.message = message;\n this.response = response;\n }\n}\n\nexport class BaseService {\n public bearerToken: string | undefined;\n public apiKey: string | undefined;\n public serviceUrl: string | undefined;\n public environment: string;\n public myAccountId: string;\n public baseDomain: string;\n public environmentOverrides: EnvironmentOverrides | undefined;\n public onOverride: OverrideReporter | undefined;\n\n /**\n * This service's entry in `SERVICE_URLS`, declared by every service in this\n * package. A subclass of our own that declares none resolves nothing from\n * the table and has to be given a `serviceUrl`.\n */\n public readonly serviceName?: ServiceName;\n\n constructor({\n bearerToken = undefined,\n apiKey = undefined,\n serviceUrl = undefined,\n environment = 'production',\n myAccountId = 'SYSTIMEMYACCOUNT',\n baseDomain = 'systime.dk',\n environmentOverrides = undefined,\n onOverride = undefined\n }: {\n bearerToken?: string;\n apiKey?: string;\n serviceUrl?: string;\n environment: string;\n myAccountId: string;\n baseDomain?: string;\n /**\n * Resolve individual services somewhere else than `environment` says,\n * for running a mix of local and hosted services. Build it once where\n * the application starts and hand the same object to every service.\n */\n environmentOverrides?: EnvironmentOverrides;\n /**\n * Where the notice about an applied override goes. Defaults to\n * `console.warn`, which this package writes to nowhere else.\n */\n onOverride?: OverrideReporter;\n }) {\n this.bearerToken = bearerToken;\n this.apiKey = apiKey;\n this.serviceUrl = serviceUrl;\n this.environment = environment.toLowerCase();\n this.myAccountId = myAccountId;\n this.baseDomain = baseDomain;\n this.environmentOverrides = environmentOverrides;\n this.onOverride = onOverride;\n }\n\n /**\n * The override that applies to this service, if any. An explicit\n * `environmentOverrides` entry beats the developer's ambient configuration,\n * and ambient configuration is not read at all in production: config that\n * arrives out of band is a hazard there whatever it happens to say.\n */\n protected findOverride():\n | { value: string; source: OverrideSource }\n | undefined {\n if (!this.serviceName) {\n return undefined;\n }\n\n const explicit = this.environmentOverrides?.[this.serviceName];\n if (explicit) {\n return { value: explicit, source: 'environmentOverrides' };\n }\n\n if (this.environment === 'production') {\n return undefined;\n }\n\n return ambientOverride(this.serviceName);\n }\n\n /**\n * Where this service answers, for the environment it was constructed with\n * or for the one an override names in its place. Ignores `serviceUrl`;\n * `getUrlPrefix()` is what honours that.\n */\n public discoverUrlPrefix(): string {\n const service = this.serviceName;\n if (!service) {\n throw new Error('Method not implemented.');\n }\n\n const override = this.findOverride();\n if (!override) {\n return resolveServiceUrl(service, this.environment, this.baseDomain);\n }\n\n const resolved = isServiceEnvironment(override.value)\n ? resolveServiceUrl(service, override.value, this.baseDomain)\n : overrideToUrl(override.value, service, override.source);\n\n reportOverride(\n {\n service,\n environment: this.environment,\n resolved,\n source: override.source\n },\n this.onOverride\n );\n\n return resolved;\n }\n\n public getUrlPrefix(): string {\n // If the URL has been explicitly set, return it: it is the escape hatch\n // for an endpoint the table cannot know about, so it beats everything\n // else. It is worth reporting for that same reason, since it also opts\n // the caller out of every future move of that service - but only for a\n // service the table does know, as that is the only case where there was\n // anything to opt out of.\n if (this.serviceUrl) {\n if (this.serviceName) {\n reportOverride(\n {\n service: this.serviceName,\n environment: this.environment,\n resolved: this.serviceUrl,\n source: 'serviceUrl'\n },\n this.onOverride\n );\n }\n return this.serviceUrl;\n }\n return this.discoverUrlPrefix();\n }\n\n public async addAuthHeaders(requestHeaders: Headers): Promise<Headers> {\n if (this.bearerToken) {\n requestHeaders.set('Authorization', `Bearer ${this.bearerToken}`);\n } else if (this.apiKey) {\n requestHeaders.set('x-api-key', this.apiKey);\n }\n return requestHeaders;\n }\n\n async getAsync({\n url,\n headers,\n addAuthHeaders = true,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n timeout: number;\n }): Promise<Response> {\n const method = 'GET';\n return await this.callAsync({\n url,\n body: null,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async putAsync({\n url,\n headers,\n addAuthHeaders = true,\n body,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n body: string | null | undefined;\n timeout: number;\n }): Promise<Response> {\n const method = 'PUT';\n return await this.callAsync({\n url,\n body,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async postAsync({\n url,\n headers,\n addAuthHeaders = true,\n body,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n body: string | null | undefined;\n timeout: number;\n }): Promise<Response> {\n const method = 'POST';\n return await this.callAsync({\n url,\n body,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async deleteAsync({\n url,\n headers,\n addAuthHeaders = true,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n timeout: number;\n }): Promise<Response> {\n const method = 'DELETE';\n return await this.callAsync({\n url,\n body: null,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async patchAsync({\n url,\n headers,\n addAuthHeaders = true,\n body,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n body: string | null | undefined;\n timeout: number;\n }): Promise<Response> {\n const method = 'PATCH';\n return await this.callAsync({\n url,\n body,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async callAsync({\n url,\n body,\n method,\n headers,\n timeout,\n addAuthHeaders\n }: {\n url: URL | string;\n body: string | null | undefined;\n method: string;\n headers: Headers | undefined | null;\n timeout: number;\n addAuthHeaders?: boolean;\n }): Promise<Response> {\n if (!headers) {\n headers = new Headers();\n }\n\n if (addAuthHeaders) {\n headers = await this.addAuthHeaders(headers);\n }\n\n const response = await fetch(url, {\n method: method,\n body: body,\n headers: headers,\n signal: AbortSignal.timeout(timeout)\n });\n\n if (!response.ok) {\n throw new HTTPError(\n `Got ${response.status} while calling ${response.url}`,\n response\n );\n }\n return response;\n }\n}\nexport default BaseService;\n","import BaseService from './base_service.js';\n\nexport interface Tag {\n identity: string;\n resource_type: string;\n resource_name: string;\n tag_name: string;\n tag_value: string;\n}\n\nexport interface TagOutput extends Tag {\n created_at: number;\n}\n\nexport class TaggingService extends BaseService {\n readonly serviceName = 'tagging' as const;\n\n async getTagsByResource({\n identity,\n resource_type,\n resource_name,\n tag_name,\n timeout = 3000\n }: {\n identity: string;\n tag_name?: string;\n resource_type?: string;\n resource_name?: string;\n timeout?: number;\n }): Promise<TagOutput[]> {\n const url = `${this.getUrlPrefix()}/tags/by_resource/${identity}${resource_type ? `/${resource_type}` : ''}${resource_name ? `/${resource_name}` : ''}${tag_name ? `/${tag_name}` : ''}`;\n\n const headers: HeadersInit = new Headers();\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n }\n\n async getTagsByName({\n identity,\n resource_type,\n resource_name,\n tag_name,\n timeout = 3000\n }: {\n identity: string;\n tag_name: string;\n resource_type?: string;\n resource_name?: string;\n timeout?: number;\n }): Promise<TagOutput[]> {\n const url = `${this.getUrlPrefix()}/tags/by_tag_name/${identity}/${tag_name}${resource_type ? `/${resource_type}` : ''}${resource_name ? `/${resource_name}` : ''}`;\n\n const headers: HeadersInit = new Headers();\n const response = await this.getAsync({ url, headers, timeout });\n return await response.json();\n }\n\n async createTag({\n tag,\n timeout = 3000\n }: {\n tag: Tag;\n timeout?: number;\n }): Promise<TagOutput> {\n const url = `${this.getUrlPrefix()}/tags`;\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(tag),\n timeout\n });\n return await response.json();\n }\n\n async updateTag({\n tag,\n timeout = 3000\n }: {\n tag: Tag;\n timeout?: number;\n }): Promise<TagOutput> {\n const url = `${this.getUrlPrefix()}/tags`;\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(tag),\n timeout\n });\n return await response.json();\n }\n\n async deleteTag({\n identity,\n resource_type,\n resource_name,\n tag_name,\n timeout = 3000\n }: {\n identity: string;\n resource_type?: string;\n resource_name?: string;\n tag_name?: string;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/tags/${identity}${resource_type ? `/${resource_type}` : ''}${resource_name ? `/${resource_name}` : ''}${tag_name ? `/${tag_name}` : ''}`;\n\n const headers: HeadersInit = new Headers();\n const response = await this.deleteAsync({ url, headers, timeout });\n await response.json();\n return;\n }\n}\n\nexport default TaggingService;\n","import BaseService from './base_service.js';\n\nexport enum SSMLSpeechSpeeds {\n X_SLOW = 1,\n SLOW = 2,\n MEDIUM = 3,\n FAST = 4,\n X_FAST = 5\n}\n\nexport type SpeechmarkEvent = {\n time: number;\n type?: string;\n value: string;\n start?: number;\n end?: number;\n};\n\nexport interface SynthesisResponse {\n mp3url: string;\n s3: string[];\n SpeechMarks?: SpeechmarkEvent[];\n}\n\nexport interface SynthesisRequest {\n text: string;\n includeSpeechMarks?: boolean;\n voice: number;\n speed?: SSMLSpeechSpeeds;\n}\n\nexport class PollyService extends BaseService {\n readonly serviceName = 'polly' as const;\n\n async synthesize({\n body,\n timeout = 3000\n }: {\n body: SynthesisRequest;\n timeout?: number;\n }): Promise<SynthesisResponse> {\n const url = `${this.getUrlPrefix()}/synthesizeSpeech`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n}\n\nexport default PollyService;\n","import BaseService from './base_service.js';\n\nexport interface CookieConsentRequest {\n consentState: CookieConsentState;\n consentUrl: string;\n timeStamp: number;\n uuid: string;\n}\n\nexport interface CookieConsentState {\n func: number;\n stat: number;\n uuid: string;\n version: number;\n}\n\nexport interface CookieConsentResponse {\n response: string;\n}\n\nexport class CookieConsentLog extends BaseService {\n readonly serviceName = 'cookieConsentLog' as const;\n\n async logCookieConsent({\n body,\n timeout = 3000\n }: {\n body: CookieConsentRequest;\n timeout?: number;\n }): Promise<string> {\n const url = `${this.getUrlPrefix()}/log`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n addAuthHeaders: false,\n timeout\n });\n return response.text();\n }\n}\n\nexport default CookieConsentLog;\n","import BaseService from './base_service.js';\n\nexport enum HighlightResultType {\n 'highlight' = 'highlight',\n 'note' = 'note'\n}\n\nexport interface HighlightRanges {\n /** XPath of the start node, e.g. \"/div[2]/div[1]/p[3]\". */\n start: string | null;\n /** XPath of the end node. */\n end: string | null;\n startOffset: number;\n endOffset: number;\n}\n\nexport interface Highlight extends HighlightUpdate {\n id: string;\n recreationdata?: IRecreationData;\n ranges?: HighlightRanges[];\n lang?: string;\n markedupText?: string;\n createdtstamp?: number;\n}\n\nexport interface HighlightRequest {\n breadCrumb: string;\n pageTitle: string;\n externalUserId?: string;\n highlight: Highlight;\n}\n\nexport interface HighlightSearchRequest {\n searchQuery: string;\n resultType?: HighlightResultType;\n isbn?: string;\n maxResults?: number;\n vectorMinConfidence?: number;\n vectorHighConfidence?: number;\n fulltextMinScore?: number;\n}\n\nexport interface HiglightSearchMatch {\n rangeKey: number;\n confidence: number;\n texttype: HighlightResultType;\n isbn: string;\n pid: number;\n returnedItem: number;\n}\n\nexport interface HighlightSearchResponse {\n Items: HighlightResponse[];\n Matches: HiglightSearchMatch[];\n}\n\nexport interface HighlightResponse extends HighlightRequest {\n debugHostname: string;\n uidIsbnPidMyAccountIdPartitionKey: string;\n timestampSortKey: number;\n timeToDie: number;\n pid: number;\n uid: string;\n myAccountid: string;\n commentText: string;\n quote: string;\n hlcolor: string;\n isbn: string;\n}\n\nexport interface HighlightUpdate {\n hlcolor: string;\n quote: string;\n text: string;\n}\n\nexport interface HighlightUpdateRequest {\n highlight: HighlightUpdate;\n}\n\nexport interface HighlightCountResponse {\n type: HighlightResultType;\n isbn: string;\n count: number;\n}\n\nexport interface HighlightDeleteResult extends HighlightUpdateResponse {\n changed: number;\n}\n\nexport interface HighlightAddResult extends HighlightUpdateResponse {\n timestampSortKey: number;\n}\n\nexport interface HighlightUpdateResponse {\n status: string;\n}\n\ninterface IBKNGData {\n prev20TextContent?: string | null;\n next20TextContent?: string;\n cid?: number;\n isPageNote?: boolean;\n domPath?: string;\n newElementPath?: string;\n elementPath?: string;\n prevNextTextContent?: {\n before: string | null;\n after: string;\n srcText: string | null;\n };\n}\n\nexport interface ICtype {\n SiblingsCount: string; // e.g. '15'\n classes: string; // e.g. 'csc-default csc-textpic'\n}\n\nexport interface ICtypeDict {\n [cid: string]: ICtype;\n}\n\nexport interface ITextStartEndObject {\n startSelectedText: string | undefined | null; // start of selection, text value\n endSelectedText: string | undefined; // end of selection, text value '150.000';\n}\n\nexport interface IRecreationData {\n startCID: number; // id of section start, e.g. 'c319'\n numberOfSiblingsOnStartNode?: number | undefined; // sibling count adjacent to the start node, e.g. '5'\n numberofPrevSiblingsOnCIDStartNode?: number | undefined; // e.g. '1';\n startCtypes?: ICtypeDict | null | undefined; // this was never used....\n\n endCID: number;\n numberOfSiblingsOnEndNode?: number | undefined;\n numberofPrevSiblingsOnCIDEndNode?: number | undefined;\n endCTypes?: ICtypeDict | null | undefined; // this was never used ....\n\n startSelectionInnerText?: string | null | undefined; // inner html (text) of the start node that was selected\n endSelectionInnerText?: string | null | undefined; // inner html (text) of the end node that was selected\n\n mathObject?: string | null | undefined; // e.g. '0'. who knows?\n\n selectedTextStartAndEndObject?: ITextStartEndObject | undefined; // not really used in the old client\n\n totalSiblingsToCIDs?: number | undefined; // e.g. '15'\n\n ibkngData?: IBKNGData | null | undefined;\n\n specialSelectedText?: string | undefined;\n source?: any | null | undefined;\n}\n\nexport class HighlightService extends BaseService {\n readonly serviceName = 'highlight' as const;\n\n async search({\n search,\n timeout = 3000\n }: {\n search: HighlightSearchRequest;\n timeout?: number;\n }): Promise<HighlightSearchResponse> {\n const url = `${this.getUrlPrefix()}/v2/search`;\n\n const headers: HeadersInit = new Headers();\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(search),\n timeout\n });\n return response.json();\n }\n\n async deleteHighlightOrNote({\n isbn,\n pid,\n key,\n timeout = 3000\n }: {\n isbn: string;\n pid: number;\n key: number;\n timeout?: number;\n }): Promise<HighlightDeleteResult> {\n const url = `${this.getUrlPrefix()}/v2/isbn/${isbn}/pid/${pid}/key/${key}`;\n\n const headers: HeadersInit = new Headers();\n headers.append('Content-Type', 'application/json');\n const response = await this.deleteAsync({ url, headers, timeout });\n return response.json();\n }\n\n async getHighlightOrNote({\n isbn,\n pid,\n timeout = 3000\n }: {\n isbn: string;\n pid?: number;\n timeout?: number;\n }): Promise<HighlightResponse[]> {\n let url = `${this.getUrlPrefix()}/v2/isbn/${isbn}`;\n if (pid) {\n url += `/pid/${pid}`;\n }\n\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n if (response.status === 204) {\n return [];\n }\n return response.json();\n }\n\n async getHighlightOrNoteCounts({\n noteType,\n timeout = 3000\n }: {\n noteType?: HighlightResultType;\n timeout?: number;\n }): Promise<HighlightCountResponse[]> {\n let url = `${this.getUrlPrefix()}/v2/count`;\n if (noteType) {\n url += `/${noteType}`;\n }\n\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n if (response.status === 204) {\n return [];\n }\n return response.json();\n }\n\n async updateHighlightOrNote({\n payload,\n isbn,\n pid,\n key,\n timeout = 5000\n }: {\n payload: HighlightUpdateRequest;\n isbn: string;\n pid: number;\n key: number;\n timeout?: number;\n }): Promise<HighlightUpdateResponse> {\n const url = `${this.getUrlPrefix()}/v2/isbn/${isbn}/pid/${pid}/key/${key}`;\n const headers: HeadersInit = new Headers();\n\n headers.set('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(payload),\n timeout\n });\n return response.json();\n }\n\n async addHighlightOrNote({\n payload,\n isbn,\n pid,\n timeout = 5000\n }: {\n payload: HighlightRequest;\n isbn: string;\n pid: number;\n timeout?: number;\n }): Promise<HighlightAddResult> {\n const url = `${this.getUrlPrefix()}/v2/isbn/${isbn}/pid/${pid}`;\n const headers: HeadersInit = new Headers();\n\n headers.set('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(payload),\n timeout\n });\n return response.json();\n }\n}\n\nexport default HighlightService;\n","import BaseService from './base_service.js';\n\nexport class UserSettingsBase extends BaseService {\n readonly serviceName = 'userSettings' as const;\n}\n\nexport default UserSettingsBase;\n","import UserSettingsBase from './user_settings_base.js';\nimport { HTTPError } from './base_service.js';\n\nexport interface ClientSettingsResponse {\n settings: ClientSettings;\n}\nexport interface ClientSettings {\n readabilities?: Readability;\n darkMode?: boolean;\n displayMode?: DisplayModeOption;\n enableKeyboardShortcuts?: boolean;\n showBookmarks?: boolean;\n showNoteHighlights?: boolean;\n featureGalleryVersion?: number;\n highlightsSorting?: HighlightsSorting;\n readAloudStore?: ReadAloudStore;\n leftDrawerWidth?: number;\n recentSearches?: string[];\n materialListImagesView?: LayoutView;\n frontPageSections?: FrontPageSection[];\n activePublicationFilters?: ActivePublicationFilters;\n cardsView?: LayoutView;\n cardsSorting?: SortOptions;\n foldersView?: LayoutView;\n foldersSorting?: SortOptions;\n onboardingPromptTime?: string;\n showOnboardingPrompt?: boolean;\n favoritesSorting?: SortOptions;\n}\n\nexport type DisplayModeOption = 'light' | 'dark' | 'system';\n\nexport type LayoutView = 'list' | 'grid';\n\nexport interface ActivePublicationFilters {\n educations?: string[];\n displaySubjects?: string[];\n categoriesNames?: string[];\n categoriesLevels?: string[];\n publishers?: string[];\n}\n\nexport interface Readability {\n letterSpacing?: number;\n lineHeight?: number;\n textSize?: number;\n fontFamily?: FontFamily;\n}\n\nexport interface FontFamily {\n name?: string;\n defaultSize?: string;\n url?: string;\n}\n\nexport interface ReadAloudStore {\n currentVoiceSelection?: CurrentVoiceSelection;\n currentSpeedSelection?: CurrentSpeedSelection;\n}\n\nexport interface CurrentSpeedSelection {\n speed?: number;\n text?: string;\n}\n\nexport interface CurrentVoiceSelection {\n voice?: number;\n gender?: number;\n language?: number;\n}\n\nexport interface FrontPageSection {\n changeable?: boolean;\n code?: string;\n enabled?: boolean;\n name?: string;\n position?: number;\n}\n\nexport type SortOptions = 'recent' | 'alphabetical';\n\nexport type HighlightsSorting = 'newest' | 'chapters';\n\nexport class UserSettingsClientSettings extends UserSettingsBase {\n async getSettings({\n isbn,\n timeout = 5000\n }: {\n isbn: string;\n timeout?: number;\n }): Promise<ClientSettingsResponse> {\n const url = `${this.getUrlPrefix()}/clientsettings/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n try {\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n } catch (error) {\n if (error instanceof HTTPError && error.response.status === 404) {\n return { settings: {} } as ClientSettingsResponse;\n } else {\n throw error;\n }\n }\n }\n\n async setSettings({\n isbn,\n settings,\n timeout = 5000\n }: {\n isbn: string;\n settings: ClientSettings;\n timeout?: number;\n }): Promise<ClientSettingsResponse> {\n const url = `${this.getUrlPrefix()}/clientsettings/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n headers.set('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(settings),\n timeout\n });\n return response.json();\n }\n\n async deleteSettings({\n isbn,\n timeout = 5000\n }: {\n isbn: string;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/clientsettings/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n await this.deleteAsync({ url, headers, timeout });\n return;\n }\n}\n\nexport default UserSettingsClientSettings;\n","import UserSettingsBase from './user_settings_base.js';\n\nexport interface Bookmark extends BookmarkUpdate {\n createdTimeStamp: number;\n isbn?: string;\n}\n\nexport interface BookmarkUpdate {\n pageId: number;\n contentId: number;\n}\n\nexport class UserSettingsBookmarks extends UserSettingsBase {\n async setBookmark({\n isbn,\n bookmark,\n externalUserId,\n timeout = 5000\n }: {\n isbn: string;\n bookmark: BookmarkUpdate;\n externalUserId?: string;\n timeout?: number;\n }): Promise<Bookmark> {\n const url = `${this.getUrlPrefix()}/bookmark/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n if (externalUserId) {\n headers.set('external-user-id', externalUserId);\n }\n\n headers.set('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(bookmark),\n timeout\n });\n return response.json();\n }\n\n async deleteBookmark({\n isbn,\n pageId,\n contentId,\n timeout = 5000\n }: {\n isbn: string;\n pageId: number;\n contentId: number;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/bookmark/isbn/${isbn}/page/${pageId}/content/${contentId}`;\n const headers: HeadersInit = new Headers();\n\n await this.deleteAsync({ url, headers, timeout });\n return;\n }\n\n async getBookmark({\n isbn,\n pageId,\n timeout = 5000\n }: {\n isbn?: string;\n pageId?: number;\n timeout?: number;\n }): Promise<Bookmark[]> {\n if (!isbn && pageId) {\n throw new Error('The isbn parameter is required if pageId is provided.');\n }\n\n let url = `${this.getUrlPrefix()}/bookmark/`;\n if (isbn) {\n url += `isbn/${isbn}`;\n }\n\n if (pageId) {\n url += `/page/${pageId}`;\n }\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n }\n\n // Favourites are bookmarks that are ISBN specific, with a pageId of 0.\n async getFavourite({\n timeout = 5000\n }: {\n timeout?: number;\n }): Promise<Bookmark[]> {\n let url = `${this.getUrlPrefix()}/bookmark/favourite`;\n\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n }\n}\n\nexport default UserSettingsBookmarks;\n","import UserSettingsBase from './user_settings_base.js';\nimport { HTTPError } from './base_service.js';\n\nexport interface Continue extends ContinueUpdate {\n createdTimeStamp?: number;\n}\n\nexport interface ContinueUpdate {\n pageId: number;\n}\n\nexport class UserSettingsContinue extends UserSettingsBase {\n async setContinue({\n isbn,\n pageId,\n externalUserId,\n timeout = 5000\n }: {\n isbn: string;\n pageId: number;\n externalUserId?: string;\n timeout?: number;\n }): Promise<Continue> {\n const continueBody: ContinueUpdate = {\n pageId\n };\n const url = `${this.getUrlPrefix()}/continue/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n if (externalUserId) {\n headers.set('external-user-id', externalUserId);\n }\n\n headers.set('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(continueBody),\n timeout\n });\n return response.json();\n }\n\n async deleteContinue({\n isbn,\n timeout = 5000\n }: {\n isbn: string;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/continue/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n await this.deleteAsync({ url, headers, timeout });\n return;\n }\n\n async getContinue({\n isbn,\n timeout = 5000\n }: {\n isbn: string;\n timeout?: number;\n }): Promise<Continue> {\n let url = `${this.getUrlPrefix()}/continue/isbn/${isbn}`;\n\n const headers: HeadersInit = new Headers();\n\n try {\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n } catch (error) {\n if (error instanceof HTTPError && error.response.status === 404) {\n return {} as Continue;\n } else {\n throw error;\n }\n }\n }\n}\n\nexport default UserSettingsContinue;\n","import UserSettingsBase from './user_settings_base.js';\n\nexport interface MRU {\n isbn: string;\n link: string;\n title: string;\n}\n\nexport class UserSettingsMRU extends UserSettingsBase {\n async setMRU({\n mru,\n externalUserId,\n timeout = 5000\n }: {\n mru: MRU;\n externalUserId?: string;\n timeout?: number;\n }): Promise<MRU[]> {\n const url = `${this.getUrlPrefix()}/mru`;\n const headers: HeadersInit = new Headers();\n\n if (externalUserId) {\n headers.set('external-user-id', externalUserId);\n }\n\n headers.set('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(mru),\n timeout\n });\n return response.json();\n }\n\n async clearMRU({ timeout = 5000 }: { timeout?: number }): Promise<void> {\n const url = `${this.getUrlPrefix()}/mru`;\n const headers: HeadersInit = new Headers();\n\n await this.deleteAsync({ url, headers, timeout });\n return;\n }\n\n async getMRU({ timeout = 5000 }: { timeout?: number }): Promise<MRU[]> {\n let url = `${this.getUrlPrefix()}/mru`;\n\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n }\n}\n\nexport default UserSettingsMRU;\n","import BaseService from './base_service.js';\n\nexport interface NoteHighlight {\n color: string;\n comment: string;\n selectedText: string;\n}\n\nexport interface Notes {\n created: string;\n highlight: NoteHighlight;\n link: string;\n pid: string;\n title: string;\n /** Not read by the export; kept for callers that carry one. */\n id?: string;\n}\n\nexport interface NotesLabels {\n amountOfNotesProse: string;\n documentTitle: string;\n markedText: string;\n noContentLabel: string;\n noSelectedTextLabel: string;\n notesExportedAt: string;\n yourNote: string;\n}\n\nexport interface NotesData {\n labels: NotesLabels;\n notes: Notes[];\n}\n\nexport interface NotesRequest {\n exportedDate: string;\n notesData: NotesData;\n userId: string;\n userName: string;\n}\n\n/** What every export answers with: a status and a link to the document. */\nexport interface PdfExportResult {\n status: string;\n url: string;\n}\n\n/**\n * @deprecated Use {@link PdfExportResult}. This name shadows the DOM `Response`\n * inside this module and for anyone importing it, which reads as though the\n * exports resolve to a fetch response rather than the parsed body.\n */\nexport type Response = PdfExportResult;\n\nexport interface WritingTaskRequest {\n pdftitle: string;\n userId: string;\n userName: string;\n writingTaskData: WritingTaskData;\n}\n\nexport interface WritingTaskData {\n createdDate: string;\n exportedDateTimeString: string;\n header: string;\n headerStripped: string;\n host: string;\n isbn: string;\n publisher: string;\n siteTitle: string;\n userIdentity: string;\n writingTaskItems: WritingTaskItem[];\n}\n\n/**\n * One task on the export. Callers pass the TYPO3 rows they hold, so only the\n * fields the export actually reads are described here and none are required:\n * the template renders the parsed pair, the title and whether the task was\n * answered, and the controller builds the images from the gallery.\n *\n * `gallery` and `images` are left open because their shapes come from the\n * caller's own content model, and the export walks them defensively.\n */\nexport interface WritingTaskItem {\n /** Rendered by the export; derive it from `answer` before sending. */\n parsedAnswer?: string;\n /** Rendered by the export; derive it from `question` before sending. */\n parsedQuestion?: string;\n title?: string;\n userAnswered?: boolean;\n /** Read for `position`, and for `rows[].columns[]` when building images. */\n gallery?: unknown;\n /** Filled in by the export from the gallery; senders may omit it. */\n images?: unknown;\n /** Only compared against zero, so a count or a list both work. */\n files?: number | string[] | null;\n answer?: string;\n question?: string;\n // Row bookkeeping the export does not read, in either spelling.\n crdate?: number;\n cruserId?: number;\n cruser_id?: number;\n deleted?: boolean | number;\n hidden?: boolean | number;\n imageorient?: number;\n parentid?: number;\n parenttable?: string;\n pid?: number;\n sorting?: number;\n tstamp?: number;\n uid?: number;\n}\n\nexport interface SiteMapLabels {\n pbook: string;\n toc: string;\n}\n\nexport interface SiteMapPageTreeItem {\n chapterInfo?: SiteMapPageTreeItem;\n characters: number;\n iPages: number;\n images: number;\n interactiveElements: number;\n lang: number;\n math: number;\n ogStandardPage: number;\n originalMaterial: number;\n quizzes: number;\n soundFiles: number;\n standardPage: number;\n sys_language_uid: number;\n uid: number;\n videos: number;\n words: number;\n}\n\n/**\n * A page in the sitemap export. The template renders `link`, `title`, `uid`\n * and `children`; everything else is whatever the caller's navigation happens\n * to carry, so it is optional here.\n */\nexport interface SiteMapPage {\n children: SiteMapPage[];\n link: string;\n title: string;\n uid: number;\n accessGranted?: boolean;\n author?: null | string;\n description?: null | string;\n doktype?: number;\n editor?: null | string;\n fe_group?: string;\n keywords?: null | string;\n nav_hide?: number;\n nav_title?: string;\n pid?: number;\n}\n\nexport type SiteMapPageTreeData = Record<string, SiteMapPageTreeItem>;\n\nexport interface SiteMapContent {\n labels: SiteMapLabels;\n pageTreeData: SiteMapPageTreeData;\n pages: SiteMapPage[];\n}\n\nexport interface SiteMapRequest {\n baseUrl: string;\n content: SiteMapContent;\n exportedDate: string;\n isbn: string;\n siteTitle: string;\n userId: string;\n userName: string;\n}\n\nexport interface PrintGlossary {\n term: string;\n description: string;\n}\n\n/**\n * A content element as the reader hands it over. The export walks\n * `content.content` for the body text, header, images and position, and the\n * shapes differ per element type, so this stays open.\n */\nexport interface PrintContentElement {\n [field: string]: unknown;\n}\n\n/**\n * Body for the print export. `contentElements` is what gets rendered; the rest\n * is page furniture. `lang` falls back to Danish server side when absent or\n * not a plain language code.\n */\nexport interface PrintRequest {\n contentElements: PrintContentElement[];\n isbn: string;\n userId: string;\n userName: string;\n baseUrl?: string;\n copyright?: string;\n disclaimer?: string;\n filename?: string;\n glossaries?: PrintGlossary[];\n lang?: string;\n pageTitle?: string;\n pnLabel?: string;\n publisher?: string;\n siteTitle?: string;\n}\n\nexport class PdfGeneratorService extends BaseService {\n readonly serviceName = 'pdfGenerator' as const;\n\n async pdfFromSiteMap({\n body,\n timeout = 3000\n }: {\n body: SiteMapRequest;\n timeout?: number;\n }): Promise<PdfExportResult> {\n const url = `${this.getUrlPrefix()}/sitemap`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n\n async pdfFromWritingTask({\n body,\n timeout = 3000\n }: {\n body: WritingTaskRequest;\n timeout?: number;\n }): Promise<PdfExportResult> {\n const url = `${this.getUrlPrefix()}/writingTask`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n\n async pdfFromPrint({\n body,\n timeout = 3000\n }: {\n body: PrintRequest;\n timeout?: number;\n }): Promise<PdfExportResult> {\n const url = `${this.getUrlPrefix()}/print`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n\n async pdfFromNotes({\n body,\n timeout = 3000\n }: {\n body: NotesRequest;\n timeout?: number;\n }): Promise<PdfExportResult> {\n const url = `${this.getUrlPrefix()}/notes`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n}\nexport default PdfGeneratorService;\n","import TaggingService from '../../tagging_service.js';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport interface FolderObject {\n created_at: number;\n}\n\nexport interface Folder extends FolderObject {\n name: string;\n color: string;\n uuid: string;\n parent?: string;\n}\n\nexport interface FolderContent extends FolderObject {\n type: string;\n identifier: string;\n folder_uuid: string;\n}\n\n/**\n * UserFolders is a service that allows users to create folders in their account. It's built on top of the Tagging service.\n * Folders are created with a name and an optional parent folder. If no parent folder is provided, the folder is created at the root level.\n * Folders are created with a unique UUID that can be used to reference the folder in future requests. The folder properties are stored as a base64 encoded JSON string.\n **/\nexport class UserFolders extends TaggingService {\n private readonly hasNoParent: string = '-';\n private identity?: string = undefined;\n\n async getIdentity(): Promise<string> {\n if (this.identity) {\n return this.identity;\n }\n\n if (this.bearerToken) {\n const tokenParts = this.bearerToken.split('.');\n const payload = Buffer.from(tokenParts[1], 'base64').toString();\n const payloadObject = JSON.parse(payload);\n // The identity is the keyword user, the user's authns and the ekeysuserid (user) concatenated with an underscore\n // This value is enforced by the Tagging service and this is the only identity\n // that the Service will accept when invoked with a user specific bearer token.\n return `user_${payloadObject.authns}_${payloadObject.user}`;\n }\n\n throw new Error(\n 'The UserFolders service must be invoked with a valid bearer token'\n );\n }\n\n /**\n * Create a folder.\n * @param folder_name The name of the folder.\n * @param parent_folder_uuid The UUID of the parent folder. If no parent folder is provided, the folder is created at the root level.\n * @param color The color of the folder.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return Folder\n **/\n async createFolder({\n folder_name,\n parent_folder_uuid,\n color,\n timeout = 3000\n }: {\n folder_name: string;\n color: string;\n parent_folder_uuid?: string;\n timeout?: number;\n }): Promise<Folder> {\n const folder_payload = JSON.stringify({\n folder: folder_name,\n color: color\n });\n const tag = await this.createTag({\n tag: {\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n resource_name: uuidv4(),\n tag_name: parent_folder_uuid ?? this.hasNoParent,\n tag_value: Buffer.from(folder_payload).toString('base64')\n },\n timeout\n });\n return {\n name: folder_name,\n uuid: tag['resource_name'],\n parent: parent_folder_uuid,\n created_at: tag['created_at']\n } as Folder;\n }\n\n /**\n * Update a folder. Only name and color can be changed.\n *\n * @param folder_uuid The UUID of the folder.\n * @param folder_name The new name of the folder.\n * @param color The new color of the folder.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return Folder\n **/\n async updateFolder({\n folder_uuid,\n folder_name,\n color,\n timeout = 3000\n }: {\n folder_uuid: string;\n folder_name?: string;\n color?: string;\n timeout?: number;\n }): Promise<Folder> {\n const tags = await this.getTagsByResource({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n resource_name: folder_uuid,\n timeout\n });\n\n if (tags.length === 0) {\n throw new Error(`Folder with UUID ${folder_uuid} not found`);\n }\n\n const tag = tags[0];\n const folder_payload = JSON.parse(\n Buffer.from(tag['tag_value'], 'base64').toString()\n );\n const new_folder_name = folder_name ?? folder_payload['folder'];\n const new_color = color ?? folder_payload['color'];\n\n const new_folder_payload = JSON.stringify({\n folder: new_folder_name,\n color: new_color\n });\n\n const updatedTag = await this.updateTag({\n tag: {\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n resource_name: folder_uuid,\n tag_name: tag['tag_name'],\n tag_value: Buffer.from(new_folder_payload).toString('base64')\n },\n timeout\n });\n\n const parent =\n tag['tag_name'] === this.hasNoParent ? undefined : tag['tag_name'];\n return {\n name: new_folder_name,\n uuid: folder_uuid,\n parent: parent,\n created_at: updatedTag['created_at']\n } as Folder;\n }\n\n /**\n * List all folders in the user's account.\n *\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return Folder[]\n **/\n async listAllFolders({\n timeout = 3000\n }: {\n timeout?: number;\n }): Promise<Folder[]> {\n const tags = await this.getTagsByResource({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n timeout\n });\n\n let folders = [];\n\n for (const tag of tags) {\n const folder_payload = JSON.parse(\n Buffer.from(tag['tag_value'], 'base64').toString()\n );\n folders.push({\n name: folder_payload['folder'],\n color: folder_payload['color'],\n uuid: tag['resource_name'],\n parent:\n tag['tag_name'] === this.hasNoParent ? undefined : tag['tag_name'],\n created_at: tag['created_at']\n } as Folder);\n }\n\n return folders;\n }\n\n /**\n * List the next level of folders in the user's account.\n *\n * @param parent_folder_uuid The UUID of the parent folder. If no parent folder is provided, the folder is created at the root level.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return Folder[]\n **/\n async listNextFolderLevel({\n parent_folder_uuid,\n timeout = 3000\n }: {\n parent_folder_uuid?: string;\n timeout?: number;\n }): Promise<Folder[]> {\n let tags;\n if (!parent_folder_uuid) {\n parent_folder_uuid = this.hasNoParent;\n }\n\n tags = await this.getTagsByName({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n tag_name: parent_folder_uuid,\n timeout\n });\n\n let folders = [];\n\n for (const tag of tags) {\n const folder_payload = JSON.parse(\n Buffer.from(tag['tag_value'], 'base64').toString()\n );\n folders.push({\n name: folder_payload['folder'],\n color: folder_payload['color'],\n uuid: tag['resource_name'],\n parent:\n tag['tag_name'] === this.hasNoParent ? undefined : tag['tag_name'],\n created_at: tag['created_at']\n } as Folder);\n }\n\n return folders;\n }\n\n /**\n * List the content of a folder.\n *\n * @param folder_uuid The UUID of the folder.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return (Folder | FolderContent)[]\n **/\n async getFolderContent({\n folder_uuid,\n timeout = 3000\n }: {\n folder_uuid: string;\n timeout?: number;\n }): Promise<(Folder | FolderContent)[]> {\n let tags = await this.getTagsByName({\n identity: await this.getIdentity(),\n tag_name: folder_uuid,\n timeout\n });\n\n let content = [];\n\n for (const tag of tags) {\n if (tag['resource_type'] === 'myaccount_user_folder') {\n const folder_payload = JSON.parse(\n Buffer.from(tag['tag_value'], 'base64').toString()\n );\n content.push({\n name: folder_payload['folder'],\n color: folder_payload['color'],\n uuid: tag['resource_name'],\n parent: tag['tag_name'],\n created_at: tag['created_at']\n } as Folder);\n } else {\n content.push({\n type: tag['resource_type'],\n identifier: tag['resource_name'],\n folder_uuid: tag['tag_name'],\n created_at: tag['created_at']\n } as FolderContent);\n }\n }\n\n return content;\n }\n\n /**\n * Add a book to a folder.\n *\n * @param folder_uuid The UUID of the folder.\n * @param isbn The ISBN of the book.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return FolderContent\n **/\n async addInternetbookToFolder({\n folder_uuid,\n isbn,\n timeout = 3000\n }: {\n folder_uuid: string;\n isbn: string;\n timeout?: number;\n }): Promise<FolderContent> {\n return await this.addContentToFolder({\n folder_uuid,\n resource_type: 'internetbook',\n resource_name: isbn,\n timeout\n });\n }\n\n /**\n * Remove a book from a folder.\n *\n * @param folder_uuid The UUID of the folder.\n * @param isbn The ISBN of the book.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return void\n **/\n async removeInternetbookFromFolder({\n folder_uuid,\n isbn,\n timeout = 3000\n }: {\n folder_uuid: string;\n isbn: string;\n timeout?: number;\n }): Promise<void> {\n await this.removeContentFromFolder({\n folder_uuid,\n resource_type: 'internetbook',\n resource_name: isbn,\n timeout\n });\n }\n\n /**\n * Create a new folder content element.\n *\n * @param folder_uuid The UUID of the folder.\n * @param resource_name The name of the resource.\n * @param resource_type The type of the resource.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return FolderContent\n **/\n async addContentToFolder({\n folder_uuid,\n resource_type,\n resource_name,\n timeout = 3000\n }: {\n folder_uuid: string;\n resource_name: string;\n resource_type: string;\n timeout?: number;\n }): Promise<FolderContent> {\n const tag = await this.createTag({\n tag: {\n identity: await this.getIdentity(),\n resource_type: resource_type,\n resource_name: resource_name,\n tag_name: folder_uuid,\n tag_value: 'MYACCOUNT_USER_FOLDER'\n },\n timeout\n });\n return {\n type: resource_type,\n identifier: resource_name,\n folder_uuid,\n created_at: tag['created_at']\n } as FolderContent;\n }\n\n /**\n * Remove a folder content element.\n *\n * @param folder_uuid The UUID of the folder.\n * @param resource_name The name of the resource.\n * @param resource_type The type of the resource.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return void\n **/\n async removeContentFromFolder({\n folder_uuid,\n resource_name,\n resource_type,\n timeout = 3000\n }: {\n folder_uuid: string;\n resource_name: string;\n resource_type: string;\n timeout?: number;\n }): Promise<void> {\n await this.deleteTag({\n identity: await this.getIdentity(),\n resource_type: resource_type,\n resource_name: resource_name,\n tag_name: folder_uuid,\n timeout\n });\n }\n\n /**\n * Delete a folder.\n *\n * @param folder_uuid The UUID of the folder.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return void\n **/\n async deleteFolder({\n folder_uuid,\n timeout = 3000\n }: {\n folder_uuid: string;\n timeout?: number;\n }): Promise<void> {\n await this.deleteTag({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n resource_name: folder_uuid,\n timeout\n });\n }\n\n /**\n * Delete all folders. Note, this will not delete the content of the folders.\n *\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return void\n **/\n async deleteAllFolders({\n timeout = 3000\n }: {\n timeout?: number;\n }): Promise<void> {\n await this.deleteTag({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n timeout\n });\n }\n}\n\nexport default UserFolders;\n","import BaseService from './base_service.js';\n\nexport type AIChatRole = 'user' | 'assistant' | 'system';\n\ntype GenericContext = Record<string, unknown>;\n\nexport interface AIChatMessage<\n ContextType extends GenericContext = GenericContext\n> {\n role: AIChatRole;\n content: string;\n context?: ContextType;\n}\n\nexport interface AIChatMessageDelta<\n ContextType extends GenericContext = GenericContext\n> {\n role?: AIChatRole;\n content?: string;\n context?: ContextType;\n}\n\nexport interface AIChatCompletion<\n ContextType extends GenericContext = GenericContext\n> {\n message: AIChatMessage;\n sessionState?: unknown;\n context?: ContextType;\n}\n\nexport interface AIChatCompletionDelta<\n ContextType extends GenericContext = GenericContext\n> {\n delta: AIChatMessageDelta;\n sessionState?: unknown;\n context?: ContextType;\n}\n\nexport interface AIChatCompletionOptions<\n ContextType extends GenericContext = GenericContext\n> {\n context?: ContextType;\n sessionState?: unknown;\n}\n\nexport type AIChatCompletionRequest = {\n messages: AIChatMessage[];\n} & AIChatCompletionOptions;\n\nexport class AIBotService extends BaseService {\n readonly serviceName = 'aiBot' as const;\n\n async constructChatUrl({\n interactivityId,\n isbn,\n stream\n }: {\n interactivityId?: string;\n isbn?: string;\n stream: boolean;\n }): Promise<string> {\n if (interactivityId && isbn) {\n throw new Error('interactivityId and isbn are mutually exclusive');\n }\n\n if (!interactivityId && !isbn) {\n throw new Error('Either interactivityId or isbn must be provided');\n }\n\n let url = '';\n if (interactivityId) {\n url = `${this.getUrlPrefix()}/${interactivityId}/chat`;\n }\n\n if (isbn) {\n url = `${this.getUrlPrefix()}/interactivity_from_isbn/${isbn}`;\n }\n\n if (stream) {\n url += '/stream';\n }\n\n return url;\n }\n\n async chat({\n interactivityId,\n isbn,\n body,\n timeout = 10000\n }: {\n interactivityId?: string;\n isbn?: string;\n body: AIChatCompletionRequest;\n timeout?: number;\n }): Promise<AIChatCompletion> {\n const url = await this.constructChatUrl({\n interactivityId,\n isbn,\n stream: false\n });\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n\n async streamingChat({\n interactivityId,\n isbn,\n body,\n timeout = 10000\n }: {\n interactivityId?: string;\n isbn?: string;\n body: AIChatCompletionRequest;\n timeout?: number;\n }): Promise<ReadableStream<Uint8Array<ArrayBufferLike>>> {\n const url = await this.constructChatUrl({\n interactivityId,\n isbn,\n stream: true\n });\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n const responseBody = response.body;\n if (!responseBody) {\n throw new Error('Response body is null');\n }\n return responseBody;\n }\n}\n\nexport default AIBotService;\n","import BaseService from './base_service.js';\nimport { resolveServiceUrl } from './service_urls.js';\n\nexport interface QuizStartResponse {\n quizUnitId: number;\n}\n\nexport interface Quiz {\n quizId: number;\n quizName: string;\n quizDescription: string;\n quizFinished: boolean;\n questions?: Question[];\n quizDeadline?: number;\n quizResultAvailable?: number;\n quizStartTime?: number;\n}\n\nexport interface Question {\n questionId: number;\n name: string;\n introText: string;\n displayName: string;\n caseSensitive?: boolean;\n shuffle: boolean;\n answerChecked: boolean;\n questionType: string;\n questionTypeId: number;\n mediafile: Mediafile;\n medias: Mediafile[];\n answers: Answer[];\n chosenAnswer: ChosenAnswer[] | null;\n description: string;\n freeText: string;\n scores?: Score;\n answerBins: AnswerBins[];\n tokenized: Tokens[];\n 'chosenAnswer correctness': string;\n isEnabled: boolean;\n}\n\nexport interface FormattedQuestion extends Question {\n number: number;\n answerTime?: string | null;\n percentage: string;\n}\n\nexport interface Mediafile {\n id: number;\n placement: string;\n caption: string;\n altText: string;\n identifier: string;\n extension: string;\n mimeType: string;\n credit: string;\n width?: number;\n}\n\nexport interface ChosenAnswer {\n id: number | number[];\n answerText: string;\n created?: number;\n position: number | number[];\n mediafile: Mediafile;\n bins?: number[];\n bin?: number;\n answers?: Answer[];\n answerBins?: AnswerBins[];\n questionId: number;\n isCorrect: boolean;\n wordoption?: AnswerIcon;\n}\n\nexport interface AnswerBins {\n txt: string;\n binindex: number;\n mediafile: Mediafile;\n}\n\nexport interface Answer {\n id: number | number[];\n answerText: string;\n isCorrect: boolean;\n position: number | number[];\n mediafile?: Mediafile;\n bins?: number[];\n inputText?: {\n [key: string]: InputText;\n };\n dropdown?: DropdownMap;\n tableData?: TableData;\n wordoptions?: WordOptions;\n wordoption?: AnswerIcon;\n answerOptions?: AnswerIcon[];\n questionId?: number;\n answerBins?: AnswerBins[];\n index?: number;\n}\n\nexport interface WordOptions {\n options: WordOptionsOption[];\n answerOptions?: string[] | AnswerIcon[];\n}\n\nexport interface WordOptionsOption {\n words: string;\n answers: string;\n position: number;\n}\n\nexport interface AnswerIcon {\n abbreviation: string;\n icon: string;\n description: string;\n display: string;\n}\n\nexport interface InputText {\n answerText: string;\n bins: number[];\n id?: number;\n correctText: string;\n isCorrect: boolean;\n position: number;\n index?: number;\n maxCorrectValue?: number;\n minCorrectValue?: number;\n}\n\nexport interface InputTextMap {\n [key: string]: InputText;\n}\n\nexport interface DropdownMap {\n [key: string]: Dropdown[];\n}\n\nexport interface Dropdown {\n option: string;\n isCorrect: boolean;\n position?: number;\n index?: number;\n}\n\nexport interface DropdownFormattedOption {\n answerId: number;\n options: Dropdown[];\n originalOptions: Dropdown[];\n}\n\nexport interface TableData {\n [key: string]: {\n [key: string]: TableDataColumn | string;\n };\n}\n\nexport interface TableDataColumn {\n correctText: string;\n isCorrect: boolean;\n position: number;\n options: Dropdown[];\n minCorrectValue?: number;\n maxCorrectValue?: number;\n}\n\nexport interface QuizResult {\n Problemdata: Question[];\n QuizSession?: {\n closesAt: string | null;\n description: string;\n name: string;\n opensAt: string | null;\n problems: number;\n quizSessionId: number;\n };\n QuizUnit?: Omit<QuizUnit, 'unitScore' | 'problemScores'>;\n Results: Results;\n}\n\nexport interface Results {\n 'Number of correct': number;\n 'Number of incorrect': number;\n 'Number of not answered': number;\n 'Number of partially correct': number;\n 'Number of questions': number;\n unitScore: CalculatedScore;\n}\n\nexport interface Score {\n 'Number of correct options': number;\n 'Number of correct options chosen': number;\n 'Number of options': number;\n 'Number of options chosen': number;\n 'Percentage score': number;\n 'Student has answered'?: boolean;\n 'Token check': Tokens[];\n}\n\nexport interface WordOptionsAnswer {\n answerId?: number;\n options?: (string | AnswerIcon)[];\n text: WordOptionsAnswerText | undefined;\n index: number;\n selected?: undefined | string | AnswerIcon;\n}\n\nexport interface WordOptionsAnswerText {\n answers: string;\n words: string;\n position: number;\n}\n\nexport interface Tokens {\n correctText: string;\n diffCheck: TokensDiffCheck[];\n numberOfTokenErrors: number;\n studentAnswerText: string;\n}\n\nexport interface TokensDiffCheck {\n error: boolean;\n studentWord: string;\n correctWord: string;\n}\n\nexport interface NewAnswer {\n answerText: string;\n bins?: number[];\n id: number | number[];\n isCorrect: boolean;\n position: number | number[];\n questionId?: number;\n index?: number;\n}\n\nexport interface SaveAnswerResponse {\n Result: string;\n}\n\nexport interface SaveAnswer {\n 'question-id': number;\n 'question-type-id': number;\n 'answer-id'?: number[];\n 'answer-text'?: (string | { answers: string } | null)[];\n 'answer-position'?: number[];\n 'answer-bin'?: number[];\n 'answer-checked'?: boolean;\n}\n\nexport type QuizTextSettings = Record<string, string | number>;\n\nexport interface SharedQuizData {\n 'quiz-id'?: string | undefined;\n isbn?: string | undefined;\n title: string;\n description: string;\n 'quiz-open': number | null;\n 'quiz-close': number | null;\n 'result-available-time'?: number | null;\n 'extra-teachers': string[];\n}\n\nexport interface SharedQuizBase {\n quizUnitId?: number;\n quizSessionId?: number;\n name?: string;\n isArchived?: boolean;\n quizResultAvailable?: number | null;\n problems: number;\n}\n\nexport interface SharedTeacherQuiz extends SharedQuizBase {\n createdAt?: number;\n deactivatedProblems?: number[];\n extraTeachers?: string[];\n isExtraTeacher?: boolean;\n isPinned?: boolean;\n studentsFinished?: number;\n}\n\nexport interface FormattedSharedTeacherQuiz extends SharedTeacherQuiz {\n formattedCreatedAt?: string | null;\n}\n\nexport interface SharedQuizUserInfo {\n eKeysUserId: string;\n email: string;\n name: string;\n myAccountId: string;\n}\n\nexport interface SharedStudentQuiz extends SharedQuizBase {\n createdBy: SharedQuizUserInfo;\n startedAt: number | null;\n finishedAt: number | null;\n opensAt: number | null;\n closesAt: number | null;\n finished: boolean;\n description?: string;\n}\n\nexport interface FormattedSharedStudentQuiz extends SharedStudentQuiz {\n formattedStartedAt?: string | null;\n formattedFinishedAt?: string | null;\n}\n\nexport interface CalculatedScore {\n points: number;\n maxPoints: number;\n percentage: number;\n}\n\nexport interface QuizSession extends SharedTeacherQuiz {\n description?: string;\n opensAt: number | null;\n closesAt: number | null;\n quizUnits?: QuizUnit[];\n averageScores?: {\n byProblem: CalculatedScore[];\n overall: CalculatedScore;\n };\n}\n\nexport interface QuizUnit {\n quizUnitId: number;\n student: SharedQuizUserInfo;\n finished: boolean;\n finishedAt: number | null;\n startedAt: number | null;\n timeSpent: TimeSpent;\n unitScore: CalculatedScore;\n problemScores: ProblemScore[];\n}\n\nexport interface TimeSpent {\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n}\n\nexport interface FormattedQuizUnit extends QuizUnit {\n formattedTimeSpent?: string;\n formattedFinishedAt?: string | null;\n formattedStartedAt?: string | null;\n percentage?: string;\n total?: string;\n [key: `problem_${string}`]: ProblemField | null | undefined;\n}\n\nexport interface ProblemScore {\n mathproblem: number;\n questionTypeId: number;\n questionTypeString: string;\n score: Score;\n}\n\nexport interface ProblemField {\n value: string | null;\n status: ProblemAnswerState;\n}\n\nexport type QuizTableAction = 'copy' | 'archive' | 'delete' | 'unarchive';\nexport type QuizTableItem =\n | SharedTeacherQuiz\n | FormattedQuizUnit\n | SharedStudentQuiz;\n\nexport type SearchableKeys = 'name';\n\nexport type ProblemAnswerState =\n | 'correct'\n | 'incorrect'\n | 'partially-correct'\n | 'unanswered';\n\nexport type QuizLocalState = {\n id: number;\n isLoading: boolean;\n isApiError: boolean;\n data: Quiz | null;\n originalData: Quiz | null;\n finished: boolean;\n results: QuizResult | null;\n instantFeedback: string | null;\n showAdvancedResults: boolean;\n};\n\nexport interface QuizDescriptionData {\n quizName: string;\n quizDescription: string;\n questionsCount: number;\n opensAt: number | null;\n closesAt: number | null;\n}\n\nexport type QuizFormType = 'copy' | 'edit' | 'create';\n\nexport interface QuizFormError {\n Error: string;\n InvalidEmails?: string[];\n}\n\nexport interface QuizFormSuccess {\n quizSessionId: number;\n}\n\nexport type QuizFormResponse = QuizFormSuccess | QuizFormError;\n\nconst REQUEST_TIMEOUT = 10000; // 10 seconds\n\nexport class QuizService extends BaseService {\n readonly serviceName = 'quiz' as const;\n\n /**\n * Where a mediafile `identifier` is served from: the API prefix without its\n * path, so the host mapping stays in `SERVICE_URLS` alone and everything\n * that can redirect the API — an explicit `serviceUrl`, a per-service\n * override — carries the media with it.\n *\n * The exception is the mock server, where the app serves the fixtures\n * itself and their identifiers are already relative to it. That is asked of\n * the resolved prefix rather than of `environment`, so it stays true when a\n * caller is sent to the mock by an override, and stops being true when one\n * sends them somewhere real from the mock environment.\n */\n getMediaUrlPrefix(): string {\n const prefix = this.getUrlPrefix();\n if (prefix === resolveServiceUrl('quiz', 'test', this.baseDomain)) {\n return '';\n }\n return new URL(prefix).origin;\n }\n\n private makeHeaders(extra?: Record<string, string>): Headers {\n const headers = new Headers();\n headers.append('Content-Type', 'application/json');\n\n if (extra) {\n for (const [key, val] of Object.entries(extra)) {\n headers.append(key, val);\n }\n }\n\n return headers;\n }\n\n // ─────────────────────────────────────────────────────────────\n // Legacy Gale quizzes\n // ─────────────────────────────────────────────────────────────\n\n async checkActiveSession({\n isbn,\n quiz,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quiz: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizStartResponse> {\n const url = `${this.getUrlPrefix()}/isbn/${isbn}/quiz/${quiz}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async startQuiz({\n isbn,\n quiz,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quiz: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizStartResponse> {\n const url = `${this.getUrlPrefix()}/isbn/${isbn}/quiz/${quiz}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.postAsync({ url, headers, body: '{}', timeout });\n return await res.json();\n }\n\n async getProblems({\n isbn,\n quizUnitId,\n shared,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n shared?: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<Quiz> {\n const url = shared\n ? `${this.getUrlPrefix()}/shared/student/${quizUnitId}`\n : `${this.getUrlPrefix()}/isbn/${isbn}/student/${quizUnitId}`;\n\n const headers = this.makeHeaders(extraHeaders);\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async resetAnswer({\n isbn,\n quizUnitId,\n questionID,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n questionID: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = `${this.getUrlPrefix()}/isbn/${isbn}/student/${quizUnitId}/question/${questionID}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.putAsync({\n url,\n headers,\n body: JSON.stringify({}),\n timeout\n });\n\n return await res.json();\n }\n\n async saveAnswer({\n isbn,\n quizUnitId,\n answer,\n shared,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n answer: object;\n shared?: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<SaveAnswerResponse> {\n const url = shared\n ? `${this.getUrlPrefix()}/shared/student/${quizUnitId}`\n : `${this.getUrlPrefix()}/isbn/${isbn}/student/${quizUnitId}`;\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(answer),\n timeout\n });\n\n return await res.json();\n }\n\n async finishQuiz({\n isbn,\n quizUnitId,\n shared,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n shared?: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = shared\n ? `${this.getUrlPrefix()}/shared/student/${quizUnitId}/finish`\n : `${this.getUrlPrefix()}/isbn/${isbn}/student/${quizUnitId}`;\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.postAsync({\n url,\n headers,\n body: JSON.stringify({}),\n timeout\n });\n\n return await res.json();\n }\n\n async getResults({\n isbn,\n quizUnitId,\n shared,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n shared?: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizResult> {\n const url = shared\n ? `${this.getUrlPrefix()}/shared/student/${quizUnitId}/result`\n : `${this.getUrlPrefix()}/isbn/${isbn}/student/overview/${quizUnitId}`;\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n // ─────────────────────────────────────────────────────────────\n // Shared quizzes\n // ─────────────────────────────────────────────────────────────\n\n async addSharedQuiz({\n quizSessionId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizStartResponse> {\n const url = `${this.getUrlPrefix()}/shared/student/${quizSessionId}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.postAsync({ url, headers, body: '{}', timeout });\n return await res.json();\n }\n\n async setQuizStartTime({\n quizUnitId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizUnitId: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/shared/student/${quizUnitId}/start`;\n const headers = this.makeHeaders(extraHeaders);\n\n await this.putAsync({ url, headers, body: '{}', timeout });\n }\n\n async createSharedQuiz({\n quizData,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizData: SharedQuizData;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizFormResponse> {\n const url = `${this.getUrlPrefix()}/shared/quiz`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(quizData),\n timeout\n });\n\n return await res.json();\n }\n\n async copyEditSharedQuiz({\n quizSessionId,\n quizData,\n action,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: number;\n quizData: SharedQuizData;\n action: Exclude<QuizFormType, 'create'>;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizFormResponse> {\n const url = `${this.getUrlPrefix()}/shared/quiz/${quizSessionId}`;\n const method = action === 'edit' ? 'PUT' : 'POST';\n const headers = this.makeHeaders(extraHeaders);\n\n const res =\n method === 'PUT'\n ? await this.putAsync({\n url,\n headers,\n body: JSON.stringify(quizData),\n timeout\n })\n : await this.postAsync({\n url,\n headers,\n body: JSON.stringify(quizData),\n timeout\n });\n\n return await res.json();\n }\n\n async getTeachersQuizProblems({\n quizSessionId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT,\n includeDisabled = false\n }: {\n quizSessionId: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n includeDisabled?: boolean;\n }): Promise<Quiz> {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes/${quizSessionId}/problems?includeDisabled=${includeDisabled}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async getTeachersUnitOverview({\n quizSessionId,\n quizUnitId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: number;\n quizUnitId: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizResult> {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes/${quizSessionId}/units/${quizUnitId}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async activateDeactivateQuestion({\n quizSessionId,\n questionId,\n activate,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: string;\n questionId: number;\n activate: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = `${this.getUrlPrefix()}/shared/teacher/quiz/${quizSessionId}/question/${questionId}`;\n const method = activate ? 'PATCH' : 'DELETE';\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res =\n method === 'PATCH'\n ? await this.patchAsync({\n url,\n headers,\n body: null,\n timeout\n })\n : await this.deleteAsync({ url, headers, timeout });\n\n return await res.json();\n }\n\n async getTeachersQuizzes({\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<SharedTeacherQuiz[]> {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async getStudentsQuizzes({\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<SharedStudentQuiz[]> {\n const url = `${this.getUrlPrefix()}/shared/student/quizzes`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async getTeachersQuiz({\n quizSessionId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: string;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizSession> {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes/${quizSessionId}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async toggleArchiveQuiz({\n quizSessionId,\n archive,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: string;\n archive: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = `${this.getUrlPrefix()}/shared/quiz/${quizSessionId}`;\n const method = archive ? 'DELETE' : 'PATCH';\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res =\n method === 'DELETE'\n ? await this.deleteAsync({ url, headers, timeout })\n : await this.patchAsync({\n url,\n headers,\n body: null,\n timeout\n });\n\n return await res.json();\n }\n\n async deleteSharedQuizUnit({\n quizSessionId,\n quizUnitId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: string;\n quizUnitId: string;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes/${quizSessionId}/units/${quizUnitId}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.deleteAsync({ url, headers, timeout });\n return await res.json();\n }\n}\n\nexport default QuizService;\n","import BaseService from './base_service.js';\n\n/** One step of a user's answer, as the client stores it. */\nexport interface StepwiseTaskDataItem {\n [field: string]: unknown;\n}\n\n/**\n * The steps of an answer. The service stores whatever it is handed and reads\n * it back the same way, and the reader keeps them keyed by uid rather than in\n * a list, so both shapes are allowed here rather than one being imposed on\n * data that already exists.\n */\nexport type StepwiseTaskData =\n | StepwiseTaskDataItem[]\n | Record<string, StepwiseTaskDataItem>;\n\nexport interface WritingTaskResponse {\n cid: string;\n createdtime?: number;\n dateString?: string;\n deleted?: boolean | string;\n deletedDate?: string | null;\n isbn: string;\n myaccountId?: string;\n pid: string;\n stepwiseTaskDataItems?: StepwiseTaskData;\n uid?: string;\n userId?: string;\n}\n\n/** The service answers with one bucket per requested cid. */\nexport interface WritingTaskResponseBucket {\n Count?: number;\n ScannedCount?: number;\n Items?: WritingTaskResponse[];\n}\n\nexport interface WritingTaskAnswer {\n cid: string;\n isbn: string;\n pid: string;\n stepwiseTaskData: StepwiseTaskData;\n dateString?: string;\n mainTitle?: string;\n /** Always empty for a real user; the service stores what it is given. */\n userName?: string;\n}\n\n/**\n * The writing task service authenticates on the bearer token but still reads\n * the user from the request body, and only accepts the token when its `sub`\n * claim matches that `userId`. It also keys stored answers by user and\n * account, so both travel in every body here rather than being taken from the\n * token as the highlight service does.\n */\nexport class WritingTaskService extends BaseService {\n readonly serviceName = 'writingTask' as const;\n\n /** Answers stored for the given content ids, one bucket per cid. */\n async getResponse({\n userId,\n isbn,\n pid,\n cids,\n timeout = 5000\n }: {\n userId: string;\n isbn: string;\n pid: string;\n cids: string[];\n timeout?: number;\n }): Promise<WritingTaskResponseBucket[]> {\n const url = `${this.getUrlPrefix()}/getResponse`;\n const headers: HeadersInit = new Headers();\n headers.set('Content-Type', 'application/json');\n\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify({\n userId,\n isbn,\n pid,\n cids,\n myaccountId: this.myAccountId\n }),\n timeout\n });\n return response.json();\n }\n\n /**\n * Stores an answer. The service upserts on the content id, so this covers\n * both the first save and every later one.\n */\n async newResponse({\n userId,\n answer,\n timeout = 5000\n }: {\n userId: string;\n answer: WritingTaskAnswer;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/newResponse`;\n const headers: HeadersInit = new Headers();\n headers.set('Content-Type', 'application/json');\n\n await this.postAsync({\n url,\n headers,\n body: JSON.stringify({\n ...answer,\n userId,\n myaccountId: this.myAccountId\n }),\n timeout\n });\n }\n\n /** Marks a stored answer deleted. */\n async deleteResponse({\n userId,\n cid,\n isbn,\n pid,\n timeout = 5000\n }: {\n userId: string;\n cid: string;\n isbn: string;\n pid: string;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/deleteResponse`;\n const headers: HeadersInit = new Headers();\n headers.set('Content-Type', 'application/json');\n\n await this.postAsync({\n url,\n headers,\n body: JSON.stringify({\n userId,\n cid,\n isbn,\n pid,\n myaccountId: this.myAccountId\n }),\n timeout\n });\n }\n}\nexport default WritingTaskService;\n","import BaseService from './base_service.js';\n\nexport class SolrProxyService extends BaseService {\n readonly serviceName = 'solrProxy' as const;\n}\n\nexport default SolrProxyService;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["uuidv4"],"sources":["../src/jwt.ts","../src/services/service_urls.ts","../src/services/service_overrides.ts","../src/services/base_service.ts","../src/services/tagging_service.ts","../src/services/polly_service.ts","../src/services/cookie_consent_log.ts","../src/services/highlight_service.ts","../src/services/user_settings_base.ts","../src/services/user_settings_clientsettings.ts","../src/services/user_settings_bookmarks.ts","../src/services/user_settings_continue.ts","../src/services/user_settings_mru.ts","../src/services/pdf_generator.ts","../src/services/highlevel/tagging/user_folders.ts","../src/services/ai_bot_service.ts","../src/services/quiz_service.ts","../src/services/writing_task_service.ts","../src/services/solr_proxy_service.ts"],"sourcesContent":["// ECMAScript maximum Date time value in milliseconds: ±100 million days from epoch.\n// new Date() silently returns Invalid Date for values outside this range.\nconst MAX_DATE_MS = 8_640_000_000_000_000;\n\n/**\n * Decodes a base64url-encoded JWT segment (RFC 4648 §5).\n */\nfunction decodeBase64Url(segment: string): string {\n const base64 = segment.replace(/-/g, '+').replace(/_/g, '/');\n // Restore padding to a multiple of 4\n const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');\n try {\n return atob(padded);\n } catch {\n throw new Error('JWT payload segment is not valid base64url');\n }\n}\n\n/**\n * Extracts the expiry time from a JWT token's `exp` claim.\n *\n * The `exp` claim is a NumericDate (Unix timestamp in seconds, per RFC 7519).\n */\nexport function getJwtExpiry(token: string): Date {\n const payload = extractJWTPayload(token);\n if (!('exp' in payload)) {\n throw new Error('Invalid JWT: payload does not contain an \"exp\" claim');\n }\n\n const exp = (payload as Record<string, unknown>).exp;\n\n if (typeof exp !== 'number') {\n throw new Error(\n `Invalid JWT: \"exp\" claim must be a number, got ${typeof exp}`\n );\n }\n\n if (!Number.isFinite(exp)) {\n throw new Error(`Invalid JWT: \"exp\" claim is not a finite number`);\n }\n\n // JWT NumericDate is seconds since epoch; Date constructor takes milliseconds.\n const expMs = exp * 1000;\n if (expMs < -MAX_DATE_MS || expMs > MAX_DATE_MS) {\n throw new Error(\n `Invalid JWT: \"exp\" value (${exp}) is outside the valid JavaScript Date range`\n );\n }\n\n return new Date(expMs);\n}\n\nfunction extractJWTPayload(token: string): Record<string, unknown> {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error(\n `Invalid JWT: expected 3 dot-separated segments, got ${parts.length}`\n );\n }\n const payloadSegment = parts[1];\n if (payloadSegment.length === 0) {\n throw new Error('Invalid JWT: payload segment is empty');\n }\n const decoded = decodeBase64Url(payloadSegment);\n let payload: unknown;\n try {\n payload = JSON.parse(decoded);\n } catch {\n throw new Error('Invalid JWT: payload is not valid JSON');\n }\n if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {\n throw new Error('Invalid JWT: payload must be a JSON object');\n }\n return payload as Record<string, unknown>;\n}\n","/**\n * The `installationpurpose` values a caller may pass as `environment`, which\n * is more values than there are places to point them at.\n */\nexport const ENVIRONMENTS = [\n 'production',\n 'development',\n 'testing',\n 'local',\n 'test'\n] as const;\n\nexport type ServiceEnvironment = (typeof ENVIRONMENTS)[number];\n\nexport function isServiceEnvironment(\n value: string\n): value is ServiceEnvironment {\n return (ENVIRONMENTS as readonly string[]).includes(value);\n}\n\n/**\n * The four places a service actually runs. Several environments share one:\n * `development` and `testing` both mean staging, and having them collapse\n * here rather than in ten separate switches is what stops one of them\n * quietly drifting away from the other.\n */\ntype Target = 'production' | 'staging' | 'local' | 'mock';\n\nconst TARGETS: Record<ServiceEnvironment, Target> = {\n production: 'production',\n development: 'staging',\n testing: 'staging',\n local: 'local',\n test: 'mock'\n};\n\n/**\n * A service's four addresses. `baseDomain` is the TYPO3 installation's domain\n * and only the hosted environments use it; local ports and the mock server\n * are the same wherever the caller runs.\n */\ntype ServiceLocations = Record<Target, (baseDomain: string) => string>;\n\n/**\n * The hosted hostnames are written out rather than derived from the service\n * name: `solr-proxy-staging.eu-west-1`, `ai-bot-service-staging.eu-west-1`\n * and the whole of `quiz` already break whatever pattern one would derive,\n * and a wrong host is worth more than the repetition costs.\n *\n * The local ports are the reserved 4110-4180 block documented in the README.\n */\nexport const SERVICE_URLS = {\n userSettings: {\n production: (d) => `https://user-settings-service.services.${d}`,\n staging: (d) => `https://staging-user-settings-service.services.${d}`,\n local: () => 'http://127.0.0.1:4110',\n mock: () => 'https://localhost:3010/services/usersettingsservice'\n },\n highlight: {\n production: (d) => `https://highlights.services.${d}`,\n staging: (d) => `https://staging-highlights.services.${d}`,\n local: () => 'http://127.0.0.1:4120',\n mock: () => 'https://localhost:3010/services/highlight'\n },\n pdfGenerator: {\n production: (d) => `https://pdfgenerator.services.${d}`,\n staging: (d) => `https://staging-pdfgenerator.services.${d}`,\n local: () => 'http://127.0.0.1:4130',\n mock: () => 'https://localhost:3010/services/pdfgenerator'\n },\n writingTask: {\n production: (d) => `https://writingtask.services.${d}`,\n staging: (d) => `https://staging-writingtask.services.${d}`,\n local: () => 'http://127.0.0.1:4140',\n mock: () => 'https://localhost:3010/services/writingtask'\n },\n solrProxy: {\n production: (d) => `https://solr-proxy.eu-west-1.${d}`,\n staging: (d) => `https://solr-proxy-staging.eu-west-1.${d}`,\n local: () => 'http://127.0.0.1:4150',\n mock: () => 'https://localhost:3010/services/solrproxy'\n },\n tagging: {\n production: (d) => `https://tagging.services.${d}`,\n staging: (d) => `https://staging-tagging.services.${d}`,\n local: () => 'http://127.0.0.1:4160',\n mock: () => 'https://localhost:3010/services/tagging'\n },\n aiBot: {\n production: (d) => `https://ai-bot-service.eu-west-1.${d}`,\n staging: (d) => `https://ai-bot-service-staging.eu-west-1.${d}`,\n local: () => 'http://127.0.0.1:4170',\n mock: () => 'https://localhost:3010/services/aibotservice'\n },\n cookieConsentLog: {\n production: (d) => `https://cookieconsentlog.services.${d}`,\n staging: (d) => `https://staging-cookieconsentlog.services.${d}`,\n local: () => 'http://127.0.0.1:4180',\n mock: () => 'https://localhost:3010/services/cookieconsentlog'\n },\n polly: {\n // Its container port 3000 is taken by nuxt dev, hence 3200 rather than a\n // port from the reserved block.\n production: (d) => `https://appear-polly.services.${d}`,\n staging: (d) => `https://staging-appear-polly.services.${d}`,\n local: () => 'http://127.0.0.1:3200',\n mock: () => 'https://localhost:3010/services/polly'\n },\n quiz: {\n // Gale has no local instance, so `local` shares the staging one.\n production: () => 'https://api.iquiz.dk/api',\n staging: () => 'https://galecms.test.tibalo.dk/api',\n local: () => 'https://galecms.test.tibalo.dk/api',\n mock: () => 'https://localhost:3010/galeapi/api'\n }\n} as const satisfies Record<string, ServiceLocations>;\n\nexport type ServiceName = keyof typeof SERVICE_URLS;\n\n/**\n * Gale CMS's QA installation, which is not a target of its own: `quiz` is the\n * only service with a QA endpoint, and a fifth `Target` would oblige the other\n * nine to name one they do not have.\n *\n * It is reached by overriding `quiz` with it, so the URL stays in this file\n * and a caller who turns it on keeps tracking this package:\n *\n * ```ts\n * environmentOverrides: { quiz: GALE_QA_URL }\n * ```\n *\n * TYPO3 asks for it through `site.sso.sso_overrides.galeQaEndpointEnabled`,\n * which is a testing arrangement: honour it outside production only.\n */\nexport const GALE_QA_URL = 'https://galecms.qa.tibalo.dk/api';\n\n/** Where `service` answers in `environment`. */\nexport function resolveServiceUrl(\n service: ServiceName,\n environment: string,\n baseDomain: string\n): string {\n if (!isServiceEnvironment(environment)) {\n throw new Error(`Unknown environment: ${environment}`);\n }\n return SERVICE_URLS[service][TARGETS[environment]](baseDomain);\n}\n","/**\n * Pointing one service somewhere else than the rest.\n *\n * A caller developing locally usually wants most services from staging and\n * one from their own machine. The override says which *environment* that one\n * service resolves in, not which URL it answers on, so the caller keeps\n * tracking `service_urls.ts` for every service they did not name — and for\n * the named one too, whenever its local port moves.\n *\n * A URL is still accepted for the cases the table cannot know about (a\n * service on a non-standard port, a tunnel, a colleague's branch deploy).\n *\n * Every override is reported, because the failure mode of all of this is a\n * forgotten one: an `environmentOverrides` entry that reached a release, or\n * an environment variable exported three weeks ago.\n */\n\nimport {\n ENVIRONMENTS,\n type ServiceEnvironment,\n type ServiceName\n} from './service_urls.js';\n\n/**\n * An environment name, or a URL for the endpoints the table cannot know\n * about. The union is written this way so an editor still suggests the\n * environment names while accepting a URL alongside them.\n */\nexport type ServiceOverride = ServiceEnvironment | (string & {});\n\nexport type EnvironmentOverrides = Partial<\n Record<ServiceName, ServiceOverride>\n>;\n\n/**\n * Where an override came from. Reporting it is most of the value: \"highlight\n * is on 127.0.0.1\" is a puzzle on its own, and stops being one as soon as it\n * says which knob did it.\n */\nexport type OverrideSource =\n | 'serviceUrl'\n | 'environmentOverrides'\n | 'env'\n | 'globalThis';\n\nexport interface OverrideDetails {\n service: ServiceName;\n /** The environment the service would have resolved in otherwise. */\n environment: string;\n /** The URL it resolved to instead. */\n resolved: string;\n source: OverrideSource;\n /** The one-line form the default reporter writes to the console. */\n message: string;\n}\n\nexport type OverrideReporter = (details: OverrideDetails) => void;\n\n/**\n * Set by a dev-only Nuxt plugin or an injected script, and the only way to\n * reach the browser bundle, where there is no `process.env`.\n */\nconst GLOBAL_OVERRIDES_KEY = '__divineEnvironmentOverrides';\n\n/** `pdfGenerator` is configured as `DIVINE_ENV_PDF_GENERATOR`. */\nexport function overrideEnvVarName(service: ServiceName): string {\n return `DIVINE_ENV_${service.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase()}`;\n}\n\n/**\n * An override the developer's machine carries rather than the application's\n * code. `process.env` is read through a computed key so a bundler treats it\n * as a lookup rather than inlining a build-time value, and both accesses are\n * guarded because neither global exists everywhere this package runs.\n *\n * The environment variable wins: it is set per run of the application, so it\n * is the more deliberate of the two.\n */\nexport function ambientOverride(\n service: ServiceName\n): { value: string; source: OverrideSource } | undefined {\n const fromEnv =\n typeof process !== 'undefined' && process.env\n ? process.env[overrideEnvVarName(service)]\n : undefined;\n if (fromEnv) {\n return { value: fromEnv, source: 'env' };\n }\n\n const fromGlobal = (\n globalThis as Record<string, unknown> as {\n [GLOBAL_OVERRIDES_KEY]?: EnvironmentOverrides;\n }\n )[GLOBAL_OVERRIDES_KEY]?.[service];\n if (fromGlobal) {\n return { value: fromGlobal, source: 'globalThis' };\n }\n\n return undefined;\n}\n\n/** An override that is not an environment name has to be a URL we can call. */\nexport function overrideToUrl(\n value: string,\n service: ServiceName,\n source: OverrideSource\n): string {\n if (/^https?:\\/\\//.test(value)) {\n return value;\n }\n throw new Error(\n `Invalid ${source} override for ${service}: \"${value}\" is neither an environment (${ENVIRONMENTS.join(', ')}) nor an http(s) URL.`\n );\n}\n\n/**\n * Already-reported overrides, so a warning survives being read.\n * `getUrlPrefix()` runs on every request, and an override that warns on every\n * one of them is an override nobody reads.\n *\n * This is process-wide mutable state, which is exactly what a per-request\n * `environment` must never be kept in — but it only ever suppresses output,\n * and \"once per process\" is the cadence a server operator wants anyway.\n */\nconst reported = new Set<string>();\n\n/** Test seam: forget what has already been reported. */\nexport function resetOverrideReports(): void {\n reported.clear();\n}\n\nconst defaultReporter: OverrideReporter = (details) =>\n console.warn(details.message);\n\n/**\n * Report an override the first time it resolves. Deliberately not silenced in\n * production: an `environmentOverrides` entry that reached a release is the\n * single thing this is here to catch.\n */\nexport function reportOverride(\n {\n service,\n environment,\n resolved,\n source\n }: Omit<OverrideDetails, 'message'>,\n onOverride?: OverrideReporter\n): void {\n const key = `${source}:${service}:${resolved}`;\n if (reported.has(key)) {\n return;\n }\n reported.add(key);\n\n const message =\n `[gyldendal-divine-api] ${service} is overridden: resolved to ${resolved} ` +\n `instead of its \"${environment}\" endpoint (source: ${source}).`;\n\n (onOverride ?? defaultReporter)({\n service,\n environment,\n resolved,\n source,\n message\n });\n}\n","import {\n ambientOverride,\n overrideToUrl,\n reportOverride,\n type EnvironmentOverrides,\n type OverrideReporter,\n type OverrideSource\n} from './service_overrides.js';\nimport {\n isServiceEnvironment,\n resolveServiceUrl,\n type ServiceName\n} from './service_urls.js';\n\nexport class HTTPError extends Error {\n public response: Response;\n\n constructor(message: string, response: Response) {\n super();\n this.message = message;\n this.response = response;\n }\n}\n\nexport class BaseService {\n public bearerToken: string | undefined;\n public apiKey: string | undefined;\n public serviceUrl: string | undefined;\n public environment: string;\n public myAccountId: string;\n public baseDomain: string;\n public environmentOverrides: EnvironmentOverrides | undefined;\n public onOverride: OverrideReporter | undefined;\n\n /**\n * This service's entry in `SERVICE_URLS`, declared by every service in this\n * package. A subclass of our own that declares none resolves nothing from\n * the table and has to be given a `serviceUrl`.\n */\n public readonly serviceName?: ServiceName;\n\n constructor({\n bearerToken = undefined,\n apiKey = undefined,\n serviceUrl = undefined,\n environment = 'production',\n myAccountId = 'SYSTIMEMYACCOUNT',\n baseDomain = 'systime.dk',\n environmentOverrides = undefined,\n onOverride = undefined\n }: {\n bearerToken?: string;\n apiKey?: string;\n serviceUrl?: string;\n environment: string;\n myAccountId: string;\n baseDomain?: string;\n /**\n * Resolve individual services somewhere else than `environment` says,\n * for running a mix of local and hosted services. Build it once where\n * the application starts and hand the same object to every service.\n */\n environmentOverrides?: EnvironmentOverrides;\n /**\n * Where the notice about an applied override goes. Defaults to\n * `console.warn`, which this package writes to nowhere else.\n */\n onOverride?: OverrideReporter;\n }) {\n this.bearerToken = bearerToken;\n this.apiKey = apiKey;\n this.serviceUrl = serviceUrl;\n this.environment = environment.toLowerCase();\n this.myAccountId = myAccountId;\n this.baseDomain = baseDomain;\n this.environmentOverrides = environmentOverrides;\n this.onOverride = onOverride;\n }\n\n /**\n * The override that applies to this service, if any. An explicit\n * `environmentOverrides` entry beats the developer's ambient configuration,\n * and ambient configuration is not read at all in production: config that\n * arrives out of band is a hazard there whatever it happens to say.\n */\n protected findOverride():\n | { value: string; source: OverrideSource }\n | undefined {\n if (!this.serviceName) {\n return undefined;\n }\n\n const explicit = this.environmentOverrides?.[this.serviceName];\n if (explicit) {\n return { value: explicit, source: 'environmentOverrides' };\n }\n\n if (this.environment === 'production') {\n return undefined;\n }\n\n return ambientOverride(this.serviceName);\n }\n\n /**\n * Where this service answers, for the environment it was constructed with\n * or for the one an override names in its place. Ignores `serviceUrl`;\n * `getUrlPrefix()` is what honours that.\n */\n public discoverUrlPrefix(): string {\n const service = this.serviceName;\n if (!service) {\n throw new Error('Method not implemented.');\n }\n\n const override = this.findOverride();\n if (!override) {\n return resolveServiceUrl(service, this.environment, this.baseDomain);\n }\n\n const resolved = isServiceEnvironment(override.value)\n ? resolveServiceUrl(service, override.value, this.baseDomain)\n : overrideToUrl(override.value, service, override.source);\n\n reportOverride(\n {\n service,\n environment: this.environment,\n resolved,\n source: override.source\n },\n this.onOverride\n );\n\n return resolved;\n }\n\n public getUrlPrefix(): string {\n // If the URL has been explicitly set, return it: it is the escape hatch\n // for an endpoint the table cannot know about, so it beats everything\n // else. It is worth reporting for that same reason, since it also opts\n // the caller out of every future move of that service - but only for a\n // service the table does know, as that is the only case where there was\n // anything to opt out of.\n if (this.serviceUrl) {\n if (this.serviceName) {\n reportOverride(\n {\n service: this.serviceName,\n environment: this.environment,\n resolved: this.serviceUrl,\n source: 'serviceUrl'\n },\n this.onOverride\n );\n }\n return this.serviceUrl;\n }\n return this.discoverUrlPrefix();\n }\n\n public async addAuthHeaders(requestHeaders: Headers): Promise<Headers> {\n if (this.bearerToken) {\n requestHeaders.set('Authorization', `Bearer ${this.bearerToken}`);\n } else if (this.apiKey) {\n requestHeaders.set('x-api-key', this.apiKey);\n }\n return requestHeaders;\n }\n\n async getAsync({\n url,\n headers,\n addAuthHeaders = true,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n timeout: number;\n }): Promise<Response> {\n const method = 'GET';\n return await this.callAsync({\n url,\n body: null,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async putAsync({\n url,\n headers,\n addAuthHeaders = true,\n body,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n body: string | null | undefined;\n timeout: number;\n }): Promise<Response> {\n const method = 'PUT';\n return await this.callAsync({\n url,\n body,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async postAsync({\n url,\n headers,\n addAuthHeaders = true,\n body,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n body: string | null | undefined;\n timeout: number;\n }): Promise<Response> {\n const method = 'POST';\n return await this.callAsync({\n url,\n body,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async deleteAsync({\n url,\n headers,\n addAuthHeaders = true,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n timeout: number;\n }): Promise<Response> {\n const method = 'DELETE';\n return await this.callAsync({\n url,\n body: null,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async patchAsync({\n url,\n headers,\n addAuthHeaders = true,\n body,\n timeout\n }: {\n url: URL | string;\n headers: Headers | undefined | null;\n addAuthHeaders?: boolean;\n body: string | null | undefined;\n timeout: number;\n }): Promise<Response> {\n const method = 'PATCH';\n return await this.callAsync({\n url,\n body,\n method,\n headers,\n addAuthHeaders,\n timeout\n });\n }\n\n async callAsync({\n url,\n body,\n method,\n headers,\n timeout,\n addAuthHeaders\n }: {\n url: URL | string;\n body: string | null | undefined;\n method: string;\n headers: Headers | undefined | null;\n timeout: number;\n addAuthHeaders?: boolean;\n }): Promise<Response> {\n if (!headers) {\n headers = new Headers();\n }\n\n if (addAuthHeaders) {\n headers = await this.addAuthHeaders(headers);\n }\n\n const response = await fetch(url, {\n method: method,\n body: body,\n headers: headers,\n signal: AbortSignal.timeout(timeout)\n });\n\n if (!response.ok) {\n throw new HTTPError(\n `Got ${response.status} while calling ${response.url}`,\n response\n );\n }\n return response;\n }\n}\nexport default BaseService;\n","import BaseService from './base_service.js';\nimport type {\n Tag,\n TagOutput\n} from '@gyldendalsolutions/divine-contracts';\n\nexport class TaggingService extends BaseService {\n readonly serviceName = 'tagging' as const;\n\n async getTagsByResource({\n identity,\n resource_type,\n resource_name,\n tag_name,\n timeout = 3000\n }: {\n identity: string;\n tag_name?: string;\n resource_type?: string;\n resource_name?: string;\n timeout?: number;\n }): Promise<TagOutput[]> {\n const url = `${this.getUrlPrefix()}/tags/by_resource/${identity}${resource_type ? `/${resource_type}` : ''}${resource_name ? `/${resource_name}` : ''}${tag_name ? `/${tag_name}` : ''}`;\n\n const headers: HeadersInit = new Headers();\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n }\n\n async getTagsByName({\n identity,\n resource_type,\n resource_name,\n tag_name,\n timeout = 3000\n }: {\n identity: string;\n tag_name: string;\n resource_type?: string;\n resource_name?: string;\n timeout?: number;\n }): Promise<TagOutput[]> {\n const url = `${this.getUrlPrefix()}/tags/by_tag_name/${identity}/${tag_name}${resource_type ? `/${resource_type}` : ''}${resource_name ? `/${resource_name}` : ''}`;\n\n const headers: HeadersInit = new Headers();\n const response = await this.getAsync({ url, headers, timeout });\n return await response.json();\n }\n\n async createTag({\n tag,\n timeout = 3000\n }: {\n tag: Tag;\n timeout?: number;\n }): Promise<TagOutput> {\n const url = `${this.getUrlPrefix()}/tags`;\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(tag),\n timeout\n });\n return await response.json();\n }\n\n async updateTag({\n tag,\n timeout = 3000\n }: {\n tag: Tag;\n timeout?: number;\n }): Promise<TagOutput> {\n const url = `${this.getUrlPrefix()}/tags`;\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(tag),\n timeout\n });\n return await response.json();\n }\n\n async deleteTag({\n identity,\n resource_type,\n resource_name,\n tag_name,\n timeout = 3000\n }: {\n identity: string;\n resource_type?: string;\n resource_name?: string;\n tag_name?: string;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/tags/${identity}${resource_type ? `/${resource_type}` : ''}${resource_name ? `/${resource_name}` : ''}${tag_name ? `/${tag_name}` : ''}`;\n\n const headers: HeadersInit = new Headers();\n const response = await this.deleteAsync({ url, headers, timeout });\n await response.json();\n return;\n }\n}\n\nexport default TaggingService;\n","import BaseService from './base_service.js';\nimport type {\n SynthesisRequest,\n SynthesisResponse\n} from '@gyldendalsolutions/divine-contracts';\n\nexport class PollyService extends BaseService {\n readonly serviceName = 'polly' as const;\n\n async synthesize({\n body,\n timeout = 3000\n }: {\n body: SynthesisRequest;\n timeout?: number;\n }): Promise<SynthesisResponse> {\n const url = `${this.getUrlPrefix()}/synthesizeSpeech`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n}\n\nexport default PollyService;\n","import BaseService from './base_service.js';\nimport type { CookieConsentRequest } from '@gyldendalsolutions/divine-contracts';\n\nexport class CookieConsentLog extends BaseService {\n readonly serviceName = 'cookieConsentLog' as const;\n\n async logCookieConsent({\n body,\n timeout = 3000\n }: {\n body: CookieConsentRequest;\n timeout?: number;\n }): Promise<string> {\n const url = `${this.getUrlPrefix()}/log`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n addAuthHeaders: false,\n timeout\n });\n return response.text();\n }\n}\n\nexport default CookieConsentLog;\n","import BaseService from './base_service.js';\nimport type {\n HighlightAddResult,\n HighlightCountResponse,\n HighlightDeleteResult,\n HighlightRequest,\n HighlightResponse,\n HighlightResultType,\n HighlightSearchRequest,\n HighlightSearchResponse,\n HighlightUpdateRequest,\n HighlightUpdateResponse\n} from '@gyldendalsolutions/divine-contracts';\n\nexport class HighlightService extends BaseService {\n readonly serviceName = 'highlight' as const;\n\n async search({\n search,\n timeout = 3000\n }: {\n search: HighlightSearchRequest;\n timeout?: number;\n }): Promise<HighlightSearchResponse> {\n const url = `${this.getUrlPrefix()}/v2/search`;\n\n const headers: HeadersInit = new Headers();\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(search),\n timeout\n });\n return response.json();\n }\n\n async deleteHighlightOrNote({\n isbn,\n pid,\n key,\n timeout = 3000\n }: {\n isbn: string;\n pid: number;\n key: number;\n timeout?: number;\n }): Promise<HighlightDeleteResult> {\n const url = `${this.getUrlPrefix()}/v2/isbn/${isbn}/pid/${pid}/key/${key}`;\n\n const headers: HeadersInit = new Headers();\n headers.append('Content-Type', 'application/json');\n const response = await this.deleteAsync({ url, headers, timeout });\n return response.json();\n }\n\n async getHighlightOrNote({\n isbn,\n pid,\n timeout = 3000\n }: {\n isbn: string;\n pid?: number;\n timeout?: number;\n }): Promise<HighlightResponse[]> {\n let url = `${this.getUrlPrefix()}/v2/isbn/${isbn}`;\n if (pid) {\n url += `/pid/${pid}`;\n }\n\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n if (response.status === 204) {\n return [];\n }\n return response.json();\n }\n\n async getHighlightOrNoteCounts({\n noteType,\n timeout = 3000\n }: {\n noteType?: HighlightResultType;\n timeout?: number;\n }): Promise<HighlightCountResponse[]> {\n let url = `${this.getUrlPrefix()}/v2/count`;\n if (noteType) {\n url += `/${noteType}`;\n }\n\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n if (response.status === 204) {\n return [];\n }\n return response.json();\n }\n\n async updateHighlightOrNote({\n payload,\n isbn,\n pid,\n key,\n timeout = 5000\n }: {\n payload: HighlightUpdateRequest;\n isbn: string;\n pid: number;\n key: number;\n timeout?: number;\n }): Promise<HighlightUpdateResponse> {\n const url = `${this.getUrlPrefix()}/v2/isbn/${isbn}/pid/${pid}/key/${key}`;\n const headers: HeadersInit = new Headers();\n\n headers.set('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(payload),\n timeout\n });\n return response.json();\n }\n\n async addHighlightOrNote({\n payload,\n isbn,\n pid,\n timeout = 5000\n }: {\n payload: HighlightRequest;\n isbn: string;\n pid: number;\n timeout?: number;\n }): Promise<HighlightAddResult> {\n const url = `${this.getUrlPrefix()}/v2/isbn/${isbn}/pid/${pid}`;\n const headers: HeadersInit = new Headers();\n\n headers.set('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(payload),\n timeout\n });\n return response.json();\n }\n}\n\nexport default HighlightService;\n","import BaseService from './base_service.js';\n\nexport class UserSettingsBase extends BaseService {\n readonly serviceName = 'userSettings' as const;\n}\n\nexport default UserSettingsBase;\n","import UserSettingsBase from './user_settings_base.js';\nimport { HTTPError } from './base_service.js';\nimport type {\n ClientSettings,\n ClientSettingsResponse\n} from '@gyldendalsolutions/divine-contracts';\n\nexport class UserSettingsClientSettings extends UserSettingsBase {\n async getSettings({\n isbn,\n timeout = 5000\n }: {\n isbn: string;\n timeout?: number;\n }): Promise<ClientSettingsResponse> {\n const url = `${this.getUrlPrefix()}/clientsettings/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n try {\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n } catch (error) {\n if (error instanceof HTTPError && error.response.status === 404) {\n return { settings: {} } as ClientSettingsResponse;\n } else {\n throw error;\n }\n }\n }\n\n async setSettings({\n isbn,\n settings,\n timeout = 5000\n }: {\n isbn: string;\n settings: ClientSettings;\n timeout?: number;\n }): Promise<ClientSettingsResponse> {\n const url = `${this.getUrlPrefix()}/clientsettings/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n headers.set('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(settings),\n timeout\n });\n return response.json();\n }\n\n async deleteSettings({\n isbn,\n timeout = 5000\n }: {\n isbn: string;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/clientsettings/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n await this.deleteAsync({ url, headers, timeout });\n return;\n }\n}\n\nexport default UserSettingsClientSettings;\n","import UserSettingsBase from './user_settings_base.js';\nimport type {\n Bookmark,\n BookmarkUpdate\n} from '@gyldendalsolutions/divine-contracts';\n\nexport class UserSettingsBookmarks extends UserSettingsBase {\n async setBookmark({\n isbn,\n bookmark,\n externalUserId,\n timeout = 5000\n }: {\n isbn: string;\n bookmark: BookmarkUpdate;\n externalUserId?: string;\n timeout?: number;\n }): Promise<Bookmark> {\n const url = `${this.getUrlPrefix()}/bookmark/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n if (externalUserId) {\n headers.set('external-user-id', externalUserId);\n }\n\n headers.set('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(bookmark),\n timeout\n });\n return response.json();\n }\n\n async deleteBookmark({\n isbn,\n pageId,\n contentId,\n timeout = 5000\n }: {\n isbn: string;\n pageId: number;\n contentId: number;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/bookmark/isbn/${isbn}/page/${pageId}/content/${contentId}`;\n const headers: HeadersInit = new Headers();\n\n await this.deleteAsync({ url, headers, timeout });\n return;\n }\n\n async getBookmark({\n isbn,\n pageId,\n timeout = 5000\n }: {\n isbn?: string;\n pageId?: number;\n timeout?: number;\n }): Promise<Bookmark[]> {\n if (!isbn && pageId) {\n throw new Error('The isbn parameter is required if pageId is provided.');\n }\n\n let url = `${this.getUrlPrefix()}/bookmark/`;\n if (isbn) {\n url += `isbn/${isbn}`;\n }\n\n if (pageId) {\n url += `/page/${pageId}`;\n }\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n }\n\n // Favourites are bookmarks that are ISBN specific, with a pageId of 0.\n async getFavourite({\n timeout = 5000\n }: {\n timeout?: number;\n }): Promise<Bookmark[]> {\n let url = `${this.getUrlPrefix()}/bookmark/favourite`;\n\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n }\n}\n\nexport default UserSettingsBookmarks;\n","import UserSettingsBase from './user_settings_base.js';\nimport { HTTPError } from './base_service.js';\nimport type {\n Continue,\n ContinueUpdate\n} from '@gyldendalsolutions/divine-contracts';\n\nexport class UserSettingsContinue extends UserSettingsBase {\n async setContinue({\n isbn,\n pageId,\n externalUserId,\n timeout = 5000\n }: {\n isbn: string;\n pageId: number;\n externalUserId?: string;\n timeout?: number;\n }): Promise<Continue> {\n const continueBody: ContinueUpdate = {\n pageId\n };\n const url = `${this.getUrlPrefix()}/continue/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n if (externalUserId) {\n headers.set('external-user-id', externalUserId);\n }\n\n headers.set('Content-Type', 'application/json');\n const response = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(continueBody),\n timeout\n });\n return response.json();\n }\n\n async deleteContinue({\n isbn,\n timeout = 5000\n }: {\n isbn: string;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/continue/isbn/${isbn}`;\n const headers: HeadersInit = new Headers();\n\n await this.deleteAsync({ url, headers, timeout });\n return;\n }\n\n async getContinue({\n isbn,\n timeout = 5000\n }: {\n isbn: string;\n timeout?: number;\n }): Promise<Continue> {\n let url = `${this.getUrlPrefix()}/continue/isbn/${isbn}`;\n\n const headers: HeadersInit = new Headers();\n\n try {\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n } catch (error) {\n if (error instanceof HTTPError && error.response.status === 404) {\n return {} as Continue;\n } else {\n throw error;\n }\n }\n }\n}\n\nexport default UserSettingsContinue;\n","import UserSettingsBase from './user_settings_base.js';\nimport type { MRU } from '@gyldendalsolutions/divine-contracts';\n\nexport class UserSettingsMRU extends UserSettingsBase {\n async setMRU({\n mru,\n externalUserId,\n timeout = 5000\n }: {\n mru: MRU;\n externalUserId?: string;\n timeout?: number;\n }): Promise<MRU[]> {\n const url = `${this.getUrlPrefix()}/mru`;\n const headers: HeadersInit = new Headers();\n\n if (externalUserId) {\n headers.set('external-user-id', externalUserId);\n }\n\n headers.set('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(mru),\n timeout\n });\n return response.json();\n }\n\n async clearMRU({ timeout = 5000 }: { timeout?: number }): Promise<void> {\n const url = `${this.getUrlPrefix()}/mru`;\n const headers: HeadersInit = new Headers();\n\n await this.deleteAsync({ url, headers, timeout });\n return;\n }\n\n async getMRU({ timeout = 5000 }: { timeout?: number }): Promise<MRU[]> {\n let url = `${this.getUrlPrefix()}/mru`;\n\n const headers: HeadersInit = new Headers();\n\n const response = await this.getAsync({ url, headers, timeout });\n return response.json();\n }\n}\n\nexport default UserSettingsMRU;\n","import BaseService from './base_service.js';\nimport type {\n NotesRequest,\n PdfExportResult,\n PrintRequest,\n SiteMapRequest,\n WritingTaskRequest\n} from '@gyldendalsolutions/divine-contracts';\n\n/**\n * @deprecated Use {@link PdfExportResult}. This name shadows the DOM `Response`\n * inside this module and for anyone importing it, which reads as though the\n * exports resolve to a fetch response rather than the parsed body.\n */\nexport type Response = PdfExportResult;\n\nexport class PdfGeneratorService extends BaseService {\n readonly serviceName = 'pdfGenerator' as const;\n\n async pdfFromSiteMap({\n body,\n timeout = 3000\n }: {\n body: SiteMapRequest;\n timeout?: number;\n }): Promise<PdfExportResult> {\n const url = `${this.getUrlPrefix()}/sitemap`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n\n async pdfFromWritingTask({\n body,\n timeout = 3000\n }: {\n body: WritingTaskRequest;\n timeout?: number;\n }): Promise<PdfExportResult> {\n const url = `${this.getUrlPrefix()}/writingTask`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n\n async pdfFromPrint({\n body,\n timeout = 3000\n }: {\n body: PrintRequest;\n timeout?: number;\n }): Promise<PdfExportResult> {\n const url = `${this.getUrlPrefix()}/print`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n\n async pdfFromNotes({\n body,\n timeout = 3000\n }: {\n body: NotesRequest;\n timeout?: number;\n }): Promise<PdfExportResult> {\n const url = `${this.getUrlPrefix()}/notes`;\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n}\nexport default PdfGeneratorService;\n","import TaggingService from '../../tagging_service.js';\nimport { v4 as uuidv4 } from 'uuid';\nimport type {\n Folder,\n FolderContent,\n FolderObject\n} from '@gyldendalsolutions/divine-contracts';\n\n/**\n * UserFolders is a service that allows users to create folders in their account. It's built on top of the Tagging service.\n * Folders are created with a name and an optional parent folder. If no parent folder is provided, the folder is created at the root level.\n * Folders are created with a unique UUID that can be used to reference the folder in future requests. The folder properties are stored as a base64 encoded JSON string.\n **/\nexport class UserFolders extends TaggingService {\n private readonly hasNoParent: string = '-';\n private identity?: string = undefined;\n\n async getIdentity(): Promise<string> {\n if (this.identity) {\n return this.identity;\n }\n\n if (this.bearerToken) {\n const tokenParts = this.bearerToken.split('.');\n const payload = Buffer.from(tokenParts[1], 'base64').toString();\n const payloadObject = JSON.parse(payload);\n // The identity is the keyword user, the user's authns and the ekeysuserid (user) concatenated with an underscore\n // This value is enforced by the Tagging service and this is the only identity\n // that the Service will accept when invoked with a user specific bearer token.\n return `user_${payloadObject.authns}_${payloadObject.user}`;\n }\n\n throw new Error(\n 'The UserFolders service must be invoked with a valid bearer token'\n );\n }\n\n /**\n * Create a folder.\n * @param folder_name The name of the folder.\n * @param parent_folder_uuid The UUID of the parent folder. If no parent folder is provided, the folder is created at the root level.\n * @param color The color of the folder.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return Folder\n **/\n async createFolder({\n folder_name,\n parent_folder_uuid,\n color,\n timeout = 3000\n }: {\n folder_name: string;\n color: string;\n parent_folder_uuid?: string;\n timeout?: number;\n }): Promise<Folder> {\n const folder_payload = JSON.stringify({\n folder: folder_name,\n color: color\n });\n const tag = await this.createTag({\n tag: {\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n resource_name: uuidv4(),\n tag_name: parent_folder_uuid ?? this.hasNoParent,\n tag_value: Buffer.from(folder_payload).toString('base64')\n },\n timeout\n });\n return {\n name: folder_name,\n uuid: tag['resource_name'],\n parent: parent_folder_uuid,\n created_at: tag['created_at']\n } as Folder;\n }\n\n /**\n * Update a folder. Only name and color can be changed.\n *\n * @param folder_uuid The UUID of the folder.\n * @param folder_name The new name of the folder.\n * @param color The new color of the folder.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return Folder\n **/\n async updateFolder({\n folder_uuid,\n folder_name,\n color,\n timeout = 3000\n }: {\n folder_uuid: string;\n folder_name?: string;\n color?: string;\n timeout?: number;\n }): Promise<Folder> {\n const tags = await this.getTagsByResource({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n resource_name: folder_uuid,\n timeout\n });\n\n if (tags.length === 0) {\n throw new Error(`Folder with UUID ${folder_uuid} not found`);\n }\n\n const tag = tags[0];\n const folder_payload = JSON.parse(\n Buffer.from(tag['tag_value'], 'base64').toString()\n );\n const new_folder_name = folder_name ?? folder_payload['folder'];\n const new_color = color ?? folder_payload['color'];\n\n const new_folder_payload = JSON.stringify({\n folder: new_folder_name,\n color: new_color\n });\n\n const updatedTag = await this.updateTag({\n tag: {\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n resource_name: folder_uuid,\n tag_name: tag['tag_name'],\n tag_value: Buffer.from(new_folder_payload).toString('base64')\n },\n timeout\n });\n\n const parent =\n tag['tag_name'] === this.hasNoParent ? undefined : tag['tag_name'];\n return {\n name: new_folder_name,\n uuid: folder_uuid,\n parent: parent,\n created_at: updatedTag['created_at']\n } as Folder;\n }\n\n /**\n * List all folders in the user's account.\n *\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return Folder[]\n **/\n async listAllFolders({\n timeout = 3000\n }: {\n timeout?: number;\n }): Promise<Folder[]> {\n const tags = await this.getTagsByResource({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n timeout\n });\n\n let folders = [];\n\n for (const tag of tags) {\n const folder_payload = JSON.parse(\n Buffer.from(tag['tag_value'], 'base64').toString()\n );\n folders.push({\n name: folder_payload['folder'],\n color: folder_payload['color'],\n uuid: tag['resource_name'],\n parent:\n tag['tag_name'] === this.hasNoParent ? undefined : tag['tag_name'],\n created_at: tag['created_at']\n } as Folder);\n }\n\n return folders;\n }\n\n /**\n * List the next level of folders in the user's account.\n *\n * @param parent_folder_uuid The UUID of the parent folder. If no parent folder is provided, the folder is created at the root level.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return Folder[]\n **/\n async listNextFolderLevel({\n parent_folder_uuid,\n timeout = 3000\n }: {\n parent_folder_uuid?: string;\n timeout?: number;\n }): Promise<Folder[]> {\n let tags;\n if (!parent_folder_uuid) {\n parent_folder_uuid = this.hasNoParent;\n }\n\n tags = await this.getTagsByName({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n tag_name: parent_folder_uuid,\n timeout\n });\n\n let folders = [];\n\n for (const tag of tags) {\n const folder_payload = JSON.parse(\n Buffer.from(tag['tag_value'], 'base64').toString()\n );\n folders.push({\n name: folder_payload['folder'],\n color: folder_payload['color'],\n uuid: tag['resource_name'],\n parent:\n tag['tag_name'] === this.hasNoParent ? undefined : tag['tag_name'],\n created_at: tag['created_at']\n } as Folder);\n }\n\n return folders;\n }\n\n /**\n * List the content of a folder.\n *\n * @param folder_uuid The UUID of the folder.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return (Folder | FolderContent)[]\n **/\n async getFolderContent({\n folder_uuid,\n timeout = 3000\n }: {\n folder_uuid: string;\n timeout?: number;\n }): Promise<(Folder | FolderContent)[]> {\n let tags = await this.getTagsByName({\n identity: await this.getIdentity(),\n tag_name: folder_uuid,\n timeout\n });\n\n let content = [];\n\n for (const tag of tags) {\n if (tag['resource_type'] === 'myaccount_user_folder') {\n const folder_payload = JSON.parse(\n Buffer.from(tag['tag_value'], 'base64').toString()\n );\n content.push({\n name: folder_payload['folder'],\n color: folder_payload['color'],\n uuid: tag['resource_name'],\n parent: tag['tag_name'],\n created_at: tag['created_at']\n } as Folder);\n } else {\n content.push({\n type: tag['resource_type'],\n identifier: tag['resource_name'],\n folder_uuid: tag['tag_name'],\n created_at: tag['created_at']\n } as FolderContent);\n }\n }\n\n return content;\n }\n\n /**\n * Add a book to a folder.\n *\n * @param folder_uuid The UUID of the folder.\n * @param isbn The ISBN of the book.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return FolderContent\n **/\n async addInternetbookToFolder({\n folder_uuid,\n isbn,\n timeout = 3000\n }: {\n folder_uuid: string;\n isbn: string;\n timeout?: number;\n }): Promise<FolderContent> {\n return await this.addContentToFolder({\n folder_uuid,\n resource_type: 'internetbook',\n resource_name: isbn,\n timeout\n });\n }\n\n /**\n * Remove a book from a folder.\n *\n * @param folder_uuid The UUID of the folder.\n * @param isbn The ISBN of the book.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return void\n **/\n async removeInternetbookFromFolder({\n folder_uuid,\n isbn,\n timeout = 3000\n }: {\n folder_uuid: string;\n isbn: string;\n timeout?: number;\n }): Promise<void> {\n await this.removeContentFromFolder({\n folder_uuid,\n resource_type: 'internetbook',\n resource_name: isbn,\n timeout\n });\n }\n\n /**\n * Create a new folder content element.\n *\n * @param folder_uuid The UUID of the folder.\n * @param resource_name The name of the resource.\n * @param resource_type The type of the resource.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return FolderContent\n **/\n async addContentToFolder({\n folder_uuid,\n resource_type,\n resource_name,\n timeout = 3000\n }: {\n folder_uuid: string;\n resource_name: string;\n resource_type: string;\n timeout?: number;\n }): Promise<FolderContent> {\n const tag = await this.createTag({\n tag: {\n identity: await this.getIdentity(),\n resource_type: resource_type,\n resource_name: resource_name,\n tag_name: folder_uuid,\n tag_value: 'MYACCOUNT_USER_FOLDER'\n },\n timeout\n });\n return {\n type: resource_type,\n identifier: resource_name,\n folder_uuid,\n created_at: tag['created_at']\n } as FolderContent;\n }\n\n /**\n * Remove a folder content element.\n *\n * @param folder_uuid The UUID of the folder.\n * @param resource_name The name of the resource.\n * @param resource_type The type of the resource.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return void\n **/\n async removeContentFromFolder({\n folder_uuid,\n resource_name,\n resource_type,\n timeout = 3000\n }: {\n folder_uuid: string;\n resource_name: string;\n resource_type: string;\n timeout?: number;\n }): Promise<void> {\n await this.deleteTag({\n identity: await this.getIdentity(),\n resource_type: resource_type,\n resource_name: resource_name,\n tag_name: folder_uuid,\n timeout\n });\n }\n\n /**\n * Delete a folder.\n *\n * @param folder_uuid The UUID of the folder.\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return void\n **/\n async deleteFolder({\n folder_uuid,\n timeout = 3000\n }: {\n folder_uuid: string;\n timeout?: number;\n }): Promise<void> {\n await this.deleteTag({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n resource_name: folder_uuid,\n timeout\n });\n }\n\n /**\n * Delete all folders. Note, this will not delete the content of the folders.\n *\n * @param timeout The timeout for the request in milliseconds.\n *\n * @return void\n **/\n async deleteAllFolders({\n timeout = 3000\n }: {\n timeout?: number;\n }): Promise<void> {\n await this.deleteTag({\n identity: await this.getIdentity(),\n resource_type: 'myaccount_user_folder',\n timeout\n });\n }\n}\n\nexport default UserFolders;\n","import BaseService from './base_service.js';\nimport type {\n AIChatCompletion,\n AIChatCompletionRequest\n} from '@gyldendalsolutions/divine-contracts';\n\ntype GenericContext = Record<string, unknown>;\n\nexport class AIBotService extends BaseService {\n readonly serviceName = 'aiBot' as const;\n\n async constructChatUrl({\n interactivityId,\n isbn,\n stream\n }: {\n interactivityId?: string;\n isbn?: string;\n stream: boolean;\n }): Promise<string> {\n if (interactivityId && isbn) {\n throw new Error('interactivityId and isbn are mutually exclusive');\n }\n\n if (!interactivityId && !isbn) {\n throw new Error('Either interactivityId or isbn must be provided');\n }\n\n let url = '';\n if (interactivityId) {\n url = `${this.getUrlPrefix()}/${interactivityId}/chat`;\n }\n\n if (isbn) {\n url = `${this.getUrlPrefix()}/interactivity_from_isbn/${isbn}`;\n }\n\n if (stream) {\n url += '/stream';\n }\n\n return url;\n }\n\n async chat({\n interactivityId,\n isbn,\n body,\n timeout = 10000\n }: {\n interactivityId?: string;\n isbn?: string;\n body: AIChatCompletionRequest;\n timeout?: number;\n }): Promise<AIChatCompletion> {\n const url = await this.constructChatUrl({\n interactivityId,\n isbn,\n stream: false\n });\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n return response.json();\n }\n\n async streamingChat({\n interactivityId,\n isbn,\n body,\n timeout = 10000\n }: {\n interactivityId?: string;\n isbn?: string;\n body: AIChatCompletionRequest;\n timeout?: number;\n }): Promise<ReadableStream<Uint8Array<ArrayBufferLike>>> {\n const url = await this.constructChatUrl({\n interactivityId,\n isbn,\n stream: true\n });\n\n const headers: HeadersInit = new Headers();\n\n headers.append('Content-Type', 'application/json');\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(body),\n timeout\n });\n const responseBody = response.body;\n if (!responseBody) {\n throw new Error('Response body is null');\n }\n return responseBody;\n }\n}\n\nexport default AIBotService;\n","import BaseService from './base_service.js';\nimport { resolveServiceUrl } from './service_urls.js';\nimport type {\n Quiz,\n QuizFormResponse,\n QuizFormType,\n QuizResult,\n QuizSession,\n QuizStartResponse,\n SaveAnswerResponse,\n SharedQuizData,\n SharedStudentQuiz,\n SharedTeacherQuiz\n} from '@gyldendalsolutions/divine-contracts';\n\nconst REQUEST_TIMEOUT = 10000; // 10 seconds\n\nexport class QuizService extends BaseService {\n readonly serviceName = 'quiz' as const;\n\n /**\n * Where a mediafile `identifier` is served from: the API prefix without its\n * path, so the host mapping stays in `SERVICE_URLS` alone and everything\n * that can redirect the API — an explicit `serviceUrl`, a per-service\n * override — carries the media with it.\n *\n * The exception is the mock server, where the app serves the fixtures\n * itself and their identifiers are already relative to it. That is asked of\n * the resolved prefix rather than of `environment`, so it stays true when a\n * caller is sent to the mock by an override, and stops being true when one\n * sends them somewhere real from the mock environment.\n */\n getMediaUrlPrefix(): string {\n const prefix = this.getUrlPrefix();\n if (prefix === resolveServiceUrl('quiz', 'test', this.baseDomain)) {\n return '';\n }\n return new URL(prefix).origin;\n }\n\n private makeHeaders(extra?: Record<string, string>): Headers {\n const headers = new Headers();\n headers.append('Content-Type', 'application/json');\n\n if (extra) {\n for (const [key, val] of Object.entries(extra)) {\n headers.append(key, val);\n }\n }\n\n return headers;\n }\n\n // ─────────────────────────────────────────────────────────────\n // Legacy Gale quizzes\n // ─────────────────────────────────────────────────────────────\n\n async checkActiveSession({\n isbn,\n quiz,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quiz: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizStartResponse> {\n const url = `${this.getUrlPrefix()}/isbn/${isbn}/quiz/${quiz}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async startQuiz({\n isbn,\n quiz,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quiz: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizStartResponse> {\n const url = `${this.getUrlPrefix()}/isbn/${isbn}/quiz/${quiz}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.postAsync({ url, headers, body: '{}', timeout });\n return await res.json();\n }\n\n async getProblems({\n isbn,\n quizUnitId,\n shared,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n shared?: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<Quiz> {\n const url = shared\n ? `${this.getUrlPrefix()}/shared/student/${quizUnitId}`\n : `${this.getUrlPrefix()}/isbn/${isbn}/student/${quizUnitId}`;\n\n const headers = this.makeHeaders(extraHeaders);\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async resetAnswer({\n isbn,\n quizUnitId,\n questionID,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n questionID: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = `${this.getUrlPrefix()}/isbn/${isbn}/student/${quizUnitId}/question/${questionID}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.putAsync({\n url,\n headers,\n body: JSON.stringify({}),\n timeout\n });\n\n return await res.json();\n }\n\n async saveAnswer({\n isbn,\n quizUnitId,\n answer,\n shared,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n answer: object;\n shared?: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<SaveAnswerResponse> {\n const url = shared\n ? `${this.getUrlPrefix()}/shared/student/${quizUnitId}`\n : `${this.getUrlPrefix()}/isbn/${isbn}/student/${quizUnitId}`;\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.putAsync({\n url,\n headers,\n body: JSON.stringify(answer),\n timeout\n });\n\n return await res.json();\n }\n\n async finishQuiz({\n isbn,\n quizUnitId,\n shared,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n shared?: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = shared\n ? `${this.getUrlPrefix()}/shared/student/${quizUnitId}/finish`\n : `${this.getUrlPrefix()}/isbn/${isbn}/student/${quizUnitId}`;\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.postAsync({\n url,\n headers,\n body: JSON.stringify({}),\n timeout\n });\n\n return await res.json();\n }\n\n async getResults({\n isbn,\n quizUnitId,\n shared,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n isbn: string;\n quizUnitId: number;\n shared?: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizResult> {\n const url = shared\n ? `${this.getUrlPrefix()}/shared/student/${quizUnitId}/result`\n : `${this.getUrlPrefix()}/isbn/${isbn}/student/overview/${quizUnitId}`;\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n // ─────────────────────────────────────────────────────────────\n // Shared quizzes\n // ─────────────────────────────────────────────────────────────\n\n async addSharedQuiz({\n quizSessionId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizStartResponse> {\n const url = `${this.getUrlPrefix()}/shared/student/${quizSessionId}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.postAsync({ url, headers, body: '{}', timeout });\n return await res.json();\n }\n\n async setQuizStartTime({\n quizUnitId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizUnitId: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/shared/student/${quizUnitId}/start`;\n const headers = this.makeHeaders(extraHeaders);\n\n await this.putAsync({ url, headers, body: '{}', timeout });\n }\n\n async createSharedQuiz({\n quizData,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizData: SharedQuizData;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizFormResponse> {\n const url = `${this.getUrlPrefix()}/shared/quiz`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.postAsync({\n url,\n headers,\n body: JSON.stringify(quizData),\n timeout\n });\n\n return await res.json();\n }\n\n async copyEditSharedQuiz({\n quizSessionId,\n quizData,\n action,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: number;\n quizData: SharedQuizData;\n action: Exclude<QuizFormType, 'create'>;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizFormResponse> {\n const url = `${this.getUrlPrefix()}/shared/quiz/${quizSessionId}`;\n const method = action === 'edit' ? 'PUT' : 'POST';\n const headers = this.makeHeaders(extraHeaders);\n\n const res =\n method === 'PUT'\n ? await this.putAsync({\n url,\n headers,\n body: JSON.stringify(quizData),\n timeout\n })\n : await this.postAsync({\n url,\n headers,\n body: JSON.stringify(quizData),\n timeout\n });\n\n return await res.json();\n }\n\n async getTeachersQuizProblems({\n quizSessionId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT,\n includeDisabled = false\n }: {\n quizSessionId: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n includeDisabled?: boolean;\n }): Promise<Quiz> {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes/${quizSessionId}/problems?includeDisabled=${includeDisabled}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async getTeachersUnitOverview({\n quizSessionId,\n quizUnitId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: number;\n quizUnitId: number;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizResult> {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes/${quizSessionId}/units/${quizUnitId}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async activateDeactivateQuestion({\n quizSessionId,\n questionId,\n activate,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: string;\n questionId: number;\n activate: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = `${this.getUrlPrefix()}/shared/teacher/quiz/${quizSessionId}/question/${questionId}`;\n const method = activate ? 'PATCH' : 'DELETE';\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res =\n method === 'PATCH'\n ? await this.patchAsync({\n url,\n headers,\n body: null,\n timeout\n })\n : await this.deleteAsync({ url, headers, timeout });\n\n return await res.json();\n }\n\n async getTeachersQuizzes({\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<SharedTeacherQuiz[]> {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async getStudentsQuizzes({\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<SharedStudentQuiz[]> {\n const url = `${this.getUrlPrefix()}/shared/student/quizzes`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async getTeachersQuiz({\n quizSessionId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: string;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }): Promise<QuizSession> {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes/${quizSessionId}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.getAsync({ url, headers, timeout });\n return await res.json();\n }\n\n async toggleArchiveQuiz({\n quizSessionId,\n archive,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: string;\n archive: boolean;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = `${this.getUrlPrefix()}/shared/quiz/${quizSessionId}`;\n const method = archive ? 'DELETE' : 'PATCH';\n\n const headers = this.makeHeaders(extraHeaders);\n\n const res =\n method === 'DELETE'\n ? await this.deleteAsync({ url, headers, timeout })\n : await this.patchAsync({\n url,\n headers,\n body: null,\n timeout\n });\n\n return await res.json();\n }\n\n async deleteSharedQuizUnit({\n quizSessionId,\n quizUnitId,\n extraHeaders,\n timeout = REQUEST_TIMEOUT\n }: {\n quizSessionId: string;\n quizUnitId: string;\n extraHeaders?: Record<string, string>;\n timeout?: number;\n }) {\n const url = `${this.getUrlPrefix()}/shared/teacher/quizzes/${quizSessionId}/units/${quizUnitId}`;\n const headers = this.makeHeaders(extraHeaders);\n\n const res = await this.deleteAsync({ url, headers, timeout });\n return await res.json();\n }\n}\n\nexport default QuizService;\n","import BaseService from './base_service.js';\nimport type {\n WritingTaskAnswer,\n WritingTaskResponseBucket\n} from '@gyldendalsolutions/divine-contracts';\n\n/**\n * The writing task service authenticates on the bearer token but still reads\n * the user from the request body, and only accepts the token when its `sub`\n * claim matches that `userId`. It also keys stored answers by user and\n * account, so both travel in every body here rather than being taken from the\n * token as the highlight service does.\n */\nexport class WritingTaskService extends BaseService {\n readonly serviceName = 'writingTask' as const;\n\n /** Answers stored for the given content ids, one bucket per cid. */\n async getResponse({\n userId,\n isbn,\n pid,\n cids,\n timeout = 5000\n }: {\n userId: string;\n isbn: string;\n pid: string;\n cids: string[];\n timeout?: number;\n }): Promise<WritingTaskResponseBucket[]> {\n const url = `${this.getUrlPrefix()}/getResponse`;\n const headers: HeadersInit = new Headers();\n headers.set('Content-Type', 'application/json');\n\n const response = await this.postAsync({\n url,\n headers,\n body: JSON.stringify({\n userId,\n isbn,\n pid,\n cids,\n myaccountId: this.myAccountId\n }),\n timeout\n });\n return response.json();\n }\n\n /**\n * Stores an answer. The service upserts on the content id, so this covers\n * both the first save and every later one.\n */\n async newResponse({\n userId,\n answer,\n timeout = 5000\n }: {\n userId: string;\n answer: WritingTaskAnswer;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/newResponse`;\n const headers: HeadersInit = new Headers();\n headers.set('Content-Type', 'application/json');\n\n await this.postAsync({\n url,\n headers,\n body: JSON.stringify({\n ...answer,\n userId,\n myaccountId: this.myAccountId\n }),\n timeout\n });\n }\n\n /** Marks a stored answer deleted. */\n async deleteResponse({\n userId,\n cid,\n isbn,\n pid,\n timeout = 5000\n }: {\n userId: string;\n cid: string;\n isbn: string;\n pid: string;\n timeout?: number;\n }): Promise<void> {\n const url = `${this.getUrlPrefix()}/deleteResponse`;\n const headers: HeadersInit = new Headers();\n headers.set('Content-Type', 'application/json');\n\n await this.postAsync({\n url,\n headers,\n body: JSON.stringify({\n userId,\n cid,\n isbn,\n pid,\n myaccountId: this.myAccountId\n }),\n timeout\n });\n }\n}\nexport default WritingTaskService;\n","import BaseService from './base_service.js';\n\nexport class SolrProxyService extends BaseService {\n readonly serviceName = 'solrProxy' as const;\n}\n\nexport default SolrProxyService;\n"],"mappings":"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"}
|