feat: export parser sessions from the browser

This commit is contained in:
2026-07-22 19:50:19 +02:00
parent 239bb3c465
commit f21d97de21
7 changed files with 355 additions and 18 deletions

View File

@@ -1,5 +1,11 @@
import type { OneNotePageDto } from '../onenote/model/dto.js';
import { OneNoteExportError } from '../onenote/export/index.js';
import type {
OneNotePackageDto,
OneNotePageDto,
OneNoteSectionDto,
} from '../onenote/model/dto.js';
import type { OneNoteResource } from '../onenote/one/content-model.js';
import { createWorkerExportArtifact } from './export-adapter.js';
import {
failureFromUnknown,
openPackageForWorker,
@@ -9,7 +15,11 @@ import {
workerPageKey,
workerResourceKey,
} from './parser-adapter.js';
import type { WorkerRequest, WorkerResponse } from './worker-protocol.js';
import type {
WorkerFailure,
WorkerRequest,
WorkerResponse,
} from './worker-protocol.js';
interface ModuleWorkerScope {
onmessage: ((event: MessageEvent<WorkerRequest>) => void) | null;
@@ -17,6 +27,7 @@ interface ModuleWorkerScope {
}
interface ParserSession {
source: OneNoteSectionDto | OneNotePackageDto;
pages: Map<string, OneNotePageDto>;
resources: Map<string, OneNoteResource>;
}
@@ -26,11 +37,12 @@ const sessions = new Map<string, ParserSession>();
let sessionSequence = 0;
function createSession(
source: OneNoteSectionDto | OneNotePackageDto,
pages: Map<string, OneNotePageDto>,
resources: Map<string, OneNoteResource>
): string {
const id = `session-${++sessionSequence}`;
sessions.set(id, { pages, resources });
sessions.set(id, { source, pages, resources });
return id;
}
@@ -42,7 +54,11 @@ async function handleRequest(data: WorkerRequest): Promise<void> {
new Uint8Array(data.bytes),
data.fileName
);
const sessionId = createSession(parsed.pages, parsed.resources);
const sessionId = createSession(
parsed.section,
parsed.pages,
parsed.resources
);
workerScope.postMessage({
type: 'section',
requestId: data.requestId,
@@ -79,7 +95,11 @@ async function handleRequest(data: WorkerRequest): Promise<void> {
new Uint8Array(data.bytes),
data.fileName
);
const sessionId = createSession(parsed.pages, parsed.resources);
const sessionId = createSession(
parsed.notebook,
parsed.pages,
parsed.resources
);
workerScope.postMessage({
type: 'package',
requestId: data.requestId,
@@ -172,6 +192,45 @@ async function handleRequest(data: WorkerRequest): Promise<void> {
);
return;
}
case 'export-session': {
const session = sessions.get(data.sessionId);
if (!session) {
workerScope.postMessage({
type: 'failure',
requestId: data.requestId,
error: {
code: 'session-not-available',
message: 'The parser session is no longer available.',
recoverable: false,
},
});
return;
}
try {
const artifact = createWorkerExportArtifact(
session.source,
session.pages,
session.resources,
data.format
);
workerScope.postMessage(
{
type: 'export-artifact',
requestId: data.requestId,
sessionId: data.sessionId,
artifact,
},
[artifact.bytes]
);
} catch (error) {
workerScope.postMessage({
type: 'failure',
requestId: data.requestId,
error: exportFailureFromUnknown(error),
});
}
return;
}
case 'dispose':
sessions.delete(data.sessionId);
workerScope.postMessage({
@@ -181,6 +240,27 @@ async function handleRequest(data: WorkerRequest): Promise<void> {
}
}
function exportFailureFromUnknown(error: unknown): WorkerFailure {
if (error instanceof OneNoteExportError) {
return {
code:
error.code === 'limit-exceeded' ? 'limit-exceeded' : 'export-failed',
message: error.message,
recoverable: true,
structure: 'OneNote export',
};
}
return {
code: 'export-failed',
message:
error instanceof Error
? error.message
: 'The local notebook export could not be created.',
recoverable: true,
structure: 'OneNote export',
};
}
workerScope.onmessage = ({ data }) => {
void handleRequest(data);
};