diff --git a/packages/core/typescript/itk-wasm/src/bindgen/python-web-demo/input-parameters-python.js b/packages/core/typescript/itk-wasm/src/bindgen/python-web-demo/input-parameters-python.js
index 417ec9fa1..c7aa96cde 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/python-web-demo/input-parameters-python.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/python-web-demo/input-parameters-python.js
@@ -1,4 +1,4 @@
-import snakeCase from "../snake-case.js"
+import snakeCase from '../snake-case.js'
function inputParametersPython(functionName, indent, parameter, required) {
let initResult = ''
@@ -54,7 +54,9 @@ function inputParametersPython(functionName, indent, parameter, required) {
methodResult += `${indent} self.model.${modelProperty}['${parameterName}'] = int(self.${inputIdentifier}.value)\n\n`
break
default:
- console.error(`Unexpected interface type: ${parameter.type}`)
+ console.error(
+ `inputParametersPython: Unexpected interface type: ${parameter.type}`
+ )
process.exit(1)
}
return { init: initResult, method: methodResult }
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/python-web-demo/output-python.js b/packages/core/typescript/itk-wasm/src/bindgen/python-web-demo/output-python.js
index 3c307c4f8..758efc0e3 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/python-web-demo/output-python.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/python-web-demo/output-python.js
@@ -1,4 +1,4 @@
-import snakeCase from "../snake-case.js"
+import snakeCase from '../snake-case.js'
function outputPython(functionName, prefix, indent, parameter) {
const parameterName = snakeCase(parameter.name)
@@ -6,13 +6,13 @@ function outputPython(functionName, prefix, indent, parameter) {
let methodResult = ''
let runResult = ''
- switch(parameter.type) {
+ switch (parameter.type) {
// case 'OUTPUT_TEXT_FILE:FILE':
// case 'OUTPUT_TEXT_STREAM':
- // result += `${indent}\n`
- // result += `${indent}${snakeCase(parameter.name)}\n`
- // result += `
\n`
- // break
+ // result += `${indent}\n`
+ // result += `${indent}${snakeCase(parameter.name)}\n`
+ // result += `
\n`
+ // break
case 'OUTPUT_BINARY_FILE:FILE':
case 'OUTPUT_BINARY_STREAM':
initResult += `${indent} ${parameterName}_download_element = js.document.querySelector('#${functionName}-outputs sl-button[name=${parameter.name}-download]')\n`
@@ -53,7 +53,9 @@ function outputPython(functionName, prefix, indent, parameter) {
// result += `
\n`
// break
default:
- console.error(`Unexpected interface type: ${parameter.type}`)
+ console.error(
+ `outputPython: Unexpected interface type: ${parameter.type}`
+ )
process.exit(1)
}
return { init: initResult, method: methodResult, run: runResult }
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/all-demo-types-supported.js b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/all-demo-types-supported.js
index 62bcd99a6..37b19990e 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/all-demo-types-supported.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/all-demo-types-supported.js
@@ -12,7 +12,8 @@ const demoSupportedInputTypes = new Set([
'INPUT_JSON',
'INPUT_IMAGE',
'INPUT_MESH',
- 'INPUT_POINT_SET'
+ 'INPUT_POINT_SET',
+ 'INPUT_TRANSFORM'
])
const demoSupportedOutputTypes = new Set([
'OUTPUT_TEXT_FILE',
@@ -22,7 +23,8 @@ const demoSupportedOutputTypes = new Set([
'OUTPUT_JSON',
'OUTPUT_IMAGE',
'OUTPUT_MESH',
- 'OUTPUT_POINT_SET'
+ 'OUTPUT_POINT_SET',
+ 'OUTPUT_TRANSFORM'
])
function allDemoTypesSupported(interfaceJson) {
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/input-parameters-demo-html.js b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/input-parameters-demo-html.js
index 30a9c2453..8868c8bb7 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/input-parameters-demo-html.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/input-parameters-demo-html.js
@@ -67,6 +67,7 @@ function inputParametersDemoHtml(
case 'INPUT_JSON':
case 'INPUT_MESH':
case 'INPUT_POINT_SET':
+ case 'INPUT_TRANSFORM':
result += `${prefix}${indent}\n`
result += `${prefix}${indent}\n`
result += '
\n'
@@ -76,8 +77,11 @@ function inputParametersDemoHtml(
result += `${prefix}${indent}\n`
result += '
\n'
break
+ break
default:
- console.error(`Unexpected interface type: ${parameterType}`)
+ console.error(
+ `inputParametersDemoHtml: Unexpected interface type: ${parameterType}`
+ )
process.exit(1)
}
return result
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/input-parameters-demo-typescript.js b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/input-parameters-demo-typescript.js
index 2a99f3a6c..cf0b11d84 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/input-parameters-demo-typescript.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/input-parameters-demo-typescript.js
@@ -114,6 +114,7 @@ function inputParametersDemoTypeScript(
case 'INPUT_IMAGE':
case 'INPUT_MESH':
case 'INPUT_POINT_SET':
+ case 'INPUT_TRANSFORM':
result += `${indent}const ${inputIdentifier} = document.querySelector('#${functionName}Inputs input[name=${parameter.name}-file]')\n`
result += `${indent}${inputIdentifier}.addEventListener('change', async (event) => {\n`
result += `${indent}${indent}const dataTransfer = event.dataTransfer\n`
@@ -172,12 +173,29 @@ function inputParametersDemoTypeScript(
result += `${indent}${indent}const details = document.getElementById("${functionName}-${parameter.name}-details")\n`
result += `${indent}${indent}details.innerHTML = \`
$\{globalThis.escapeHtml(JSON.stringify(pointSet, globalThis.interfaceTypeJsonReplacer, 2))}
\`\n`
}
+ } else if (parameterType === 'INPUT_TRANSFORM') {
+ if (parameter.itemsExpectedMax > 1) {
+ result += `${indent}${indent}const readTransform = await Promise.all(Array.from(files).map(async (file) => readTransform(file)))\n`
+ result += `${indent}${indent}readTransform.forEach(t => t.webWorker.terminate())\n`
+ result += `${indent}${indent}const inputTransform = readTransform.map(t => t.transform)\n`
+ result += `${indent}${indent}model.${modelProperty}.set("${parameterName}", inputTransform)\n`
+ result += `${indent}${indent}const details = document.getElementById("${functionName}-${parameter.name}-details")\n`
+ result += `${indent}${indent}details.innerHTML = \`$\{globalThis.escapeHtml(JSON.stringify(inputTransform, globalThis.interfaceTypeJsonReplacer, 2))}
\`\n`
+ } else {
+ result += `${indent}${indent}const { transform, webWorker } = await readTransform(files[0])\n`
+ result += `${indent}${indent}webWorker.terminate()\n`
+ result += `${indent}${indent}model.${modelProperty}.set("${parameterName}", transform)\n`
+ result += `${indent}${indent}const details = document.getElementById("${functionName}-${parameter.name}-details")\n`
+ result += `${indent}${indent}details.innerHTML = \`$\{globalThis.escapeHtml(JSON.stringify(transform, globalThis.interfaceTypeJsonReplacer, 2))}
\`\n`
+ }
}
result += `${indent}${indent}details.disabled = false\n`
result += `${indent}})\n\n`
break
default:
- console.error(`Unexpected interface type: ${parameterType}`)
+ console.error(
+ `inputParametersDemoTypeScript: Unexpected interface type: ${parameterType}`
+ )
process.exit(1)
}
return result
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/interface-functions-demo-typescript.js b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/interface-functions-demo-typescript.js
index ef99aaa58..397af9116 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/interface-functions-demo-typescript.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/interface-functions-demo-typescript.js
@@ -24,9 +24,11 @@ function interfaceFunctionsDemoTypeScript(
needReadImage,
needReadMesh,
needReadPointSet,
+ needReadTransform,
needWriteImage,
needWriteMesh,
- needWritePointSet
+ needWritePointSet,
+ needWriteTransform
} = ioPackagesNeeded(interfaceJson)
if (needReadMesh) {
if (packageName === '@itk-wasm/mesh-io') {
@@ -49,6 +51,13 @@ function interfaceFunctionsDemoTypeScript(
result += `import { readImage } from '@itk-wasm/image-io'\n`
}
}
+ if (needReadTransform) {
+ if (packageName === '@itk-wasm/transform-io') {
+ result += `import { readTransform } from '../../../dist/index.js'\n`
+ } else {
+ result += `import { readTransform } from '@itk-wasm/transform-io'\n`
+ }
+ }
if (needWriteMesh) {
if (packageName === '@itk-wasm/mesh-io') {
result += `import { writeMesh } from '../../../dist/index.js'\n`
@@ -70,6 +79,13 @@ function interfaceFunctionsDemoTypeScript(
result += `import { writeImage } from '@itk-wasm/image-io'\n`
}
}
+ if (needWriteTransform) {
+ if (packageName === '@itk-wasm/transform-io') {
+ result += `import { writeTransform } from '../../../dist/index.js'\n`
+ } else {
+ result += `import { writeTransform } from '@itk-wasm/transform-io'\n`
+ }
+ }
result += `import * as ${camelCase(bundleName)} from '../../../dist/index.js'\n`
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/io-packages-needed.js b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/io-packages-needed.js
index 9c431385d..44caf6fb3 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/io-packages-needed.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/io-packages-needed.js
@@ -4,6 +4,7 @@ function ioPackagesNeeded(interfaceJson) {
let needReadMesh = false
let needReadImage = false
let needReadPointSet = false
+ let needReadTransform = false
const pipelineComponents = ['inputs', 'parameters']
pipelineComponents.forEach((pipelineComponent) => {
needReadMesh =
@@ -22,6 +23,12 @@ function ioPackagesNeeded(interfaceJson) {
interfaceJson[pipelineComponent].filter(
(value) => interfaceJsonTypeToInterfaceType.get(value.type) === 'Image'
).length > 0
+ needReadTransform =
+ needReadTransform ||
+ interfaceJson[pipelineComponent].filter(
+ (value) =>
+ interfaceJsonTypeToInterfaceType.get(value.type) === 'TransformList'
+ ).length > 0
})
const needWriteMesh =
interfaceJson.outputs.filter(
@@ -35,13 +42,20 @@ function ioPackagesNeeded(interfaceJson) {
interfaceJson.outputs.filter(
(value) => interfaceJsonTypeToInterfaceType.get(value.type) === 'Image'
).length > 0
+ const needWriteTransform =
+ interfaceJson.outputs.filter(
+ (value) =>
+ interfaceJsonTypeToInterfaceType.get(value.type) === 'TransformList'
+ ).length > 0
return {
needReadImage,
needReadMesh,
needReadPointSet,
+ needReadTransform,
needWriteImage,
needWriteMesh,
- needWritePointSet
+ needWritePointSet,
+ needWriteTransform
}
}
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-html.js b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-html.js
index d047b5b04..43810448e 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-html.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-html.js
@@ -96,8 +96,24 @@ function outputDemoHtml(functionName, prefix, indent, parameter) {
result += `
\n`
}
break
+ case 'OUTPUT_TRANSFORM':
+ {
+ result += `${prefix}${indent}\n`
+
+ result += `${prefix}${indent}\n`
+ const formats = ['h5', 'txt', 'mat', 'xfm']
+ formats.forEach((format) => {
+ result += `${prefix}${indent}${indent}${format}\n`
+ })
+ result += `${prefix}${indent}\n`
+ result += `${prefix}${indent}Download\n`
+ result += `
\n`
+ }
+ break
default:
- console.error(`Unexpected interface type: ${parameterType}`)
+ console.error(
+ `outputDemoHtml: Unexpected interface type: ${parameterType}`
+ )
process.exit(1)
}
return result
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-run-typescript.js b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-run-typescript.js
index 085e69358..4d4821c51 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-run-typescript.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-run-typescript.js
@@ -48,6 +48,7 @@ function outputDemoRunTypeScript(functionName, prefix, indent, parameter) {
case 'OUTPUT_IMAGE':
case 'OUTPUT_MESH':
case 'OUTPUT_POINT_SET':
+ case 'OUTPUT_TRANSFORM':
result += `${prefix}${indent}${parameterName}OutputDownload.variant = "success"\n`
result += `${prefix}${indent}${parameterName}OutputDownload.disabled = false\n`
result += `${indent}${indent}const ${parameterName}Details = document.getElementById("${functionName}-${parameter.name}-details")\n`
@@ -62,7 +63,9 @@ function outputDemoRunTypeScript(functionName, prefix, indent, parameter) {
}
break
default:
- console.error(`Unexpected interface type: ${parameter.type}`)
+ console.error(
+ `outputDemoRunTypeScript: Unexpected interface type: ${parameter.type}`
+ )
process.exit(1)
}
return result
diff --git a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-typescript.js b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-typescript.js
index e9e710e2b..f66de59f4 100644
--- a/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-typescript.js
+++ b/packages/core/typescript/itk-wasm/src/bindgen/typescript/demo/output-demo-typescript.js
@@ -102,8 +102,25 @@ function outputDemoTypeScript(functionName, prefix, indent, parameter) {
result += `${prefix}${indent}${indent}}\n`
result += `${prefix}${indent}})\n`
break
+ case 'OUTPUT_TRANSFORM':
+ result += `${prefix}${indent}const ${parameterName}OutputDownload = document.querySelector('#${functionName}Outputs sl-button[name=${parameter.name}-download]')\n`
+ result += `${prefix}${indent}${parameterName}OutputDownload.addEventListener('click', async (event) => {\n`
+ result += `${prefix}${indent}${indent}event.preventDefault()\n`
+ result += `${prefix}${indent}${indent}event.stopPropagation()\n`
+ result += `${prefix}${indent}${indent}if (model.outputs.has("${parameterName}")) {\n`
+ result += `${prefix}${indent}${indent}${indent}const ${parameterName}DownloadFormat = document.getElementById('${functionName}-${parameter.name}-output-format')\n`
+ result += `${prefix}${indent}${indent}${indent}const downloadFormat = ${parameterName}DownloadFormat.value || 'nrrd'\n`
+ result += `${prefix}${indent}${indent}${indent}const fileName = \`${parameterName}.\${downloadFormat}\`\n`
+ result += `${prefix}${indent}${indent}${indent}const { webWorker, serializedTransform } = await writeImage(model.outputs.get("${parameterName}"), fileName)\n\n`
+ result += `${prefix}${indent}${indent}${indent}webWorker.terminate()\n`
+ result += `${prefix}${indent}${indent}${indent}globalThis.downloadFile(serializedTransform.data, fileName)\n`
+ result += `${prefix}${indent}${indent}}\n`
+ result += `${prefix}${indent}})\n`
+ break
default:
- console.error(`Unexpected interface type: ${parameter.type}`)
+ console.error(
+ `outputDemoTypeScript: Unexpected interface type: ${parameter.type}`
+ )
process.exit(1)
}
return result
diff --git a/packages/transform-io/typescript/.gitignore b/packages/transform-io/typescript/.gitignore
new file mode 100644
index 000000000..63d1828c7
--- /dev/null
+++ b/packages/transform-io/typescript/.gitignore
@@ -0,0 +1 @@
+cypress/screenshots/
diff --git a/packages/transform-io/typescript/cypress.config.ts b/packages/transform-io/typescript/cypress.config.ts
new file mode 100644
index 000000000..1d4054ee4
--- /dev/null
+++ b/packages/transform-io/typescript/cypress.config.ts
@@ -0,0 +1,9 @@
+import { defineConfig } from "cypress";
+
+export default defineConfig({
+ e2e: {
+ defaultCommandTimeout: 40000,
+ setupNodeEvents(on, config) {
+ },
+ },
+});
diff --git a/packages/transform-io/typescript/cypress/e2e/common.ts b/packages/transform-io/typescript/cypress/e2e/common.ts
new file mode 100644
index 000000000..0c496487a
--- /dev/null
+++ b/packages/transform-io/typescript/cypress/e2e/common.ts
@@ -0,0 +1,24 @@
+export const demoServer = "http://localhost:5181";
+
+export function verifyTestLinearTransform(transformList) {
+ cy.expect(transformList.length).to.equal(1);
+ const transform = transformList[0];
+ cy.expect(transform.transformType.transformParameterization).to.equal(
+ "Affine"
+ );
+ cy.expect(transform.transformType.parametersValueType).to.equal("float64");
+ cy.expect(transform.transformType.inputDimension).to.equal(3);
+ cy.expect(transform.transformType.outputDimension).to.equal(3);
+ cy.expect(transform.numberOfParameters).to.equal(12);
+ cy.expect(transform.numberOfFixedParameters).to.equal(3);
+ cy.deepEqual(transform.fixedParameters, new Float64Array([0, 0, 0]));
+ cy.deepEqual(
+ transform.parameters,
+ new Float64Array([
+ 0.65631490118447, 0.5806583745824385, -0.4817536741017158,
+ -0.7407986817430222, 0.37486398378429736, -0.5573995934598175,
+ -0.14306664045479867, 0.7227121458012518, 0.676179776908723,
+ -65.99999999999997, 69.00000000000004, 32.000000000000036,
+ ])
+ );
+}
diff --git a/packages/transform-io/typescript/cypress/e2e/read-transform.ty.ts b/packages/transform-io/typescript/cypress/e2e/read-transform.ty.ts
new file mode 100644
index 000000000..c2ea6c47a
--- /dev/null
+++ b/packages/transform-io/typescript/cypress/e2e/read-transform.ty.ts
@@ -0,0 +1,72 @@
+import { demoServer, verifyMesh } from './common.ts'
+
+describe('read-mesh', () => {
+ beforeEach(function() {
+ cy.visit(demoServer)
+
+ const testPathPrefix = '../test/data/input/'
+
+ const testImageFiles = [
+ 'cow.vtk'
+ ]
+ testImageFiles.forEach((fileName) => {
+ cy.readFile(`${testPathPrefix}${fileName}`, null).as(fileName)
+ })
+ })
+
+ it('Reads an mesh File in the demo', function () {
+ cy.get('sl-tab[panel="readMesh-panel"]').click()
+
+ const testFile = { contents: new Uint8Array(this['cow.vtk']), fileName: 'cow.vtk' }
+ cy.get('#readMeshInputs input[name="serialized-mesh-file"]').selectFile([testFile,], { force: true })
+ cy.get('#readMesh-serialized-mesh-details').should('contain', '35,32')
+
+ cy.get('#readMeshInputs sl-button[name="run"]').click()
+
+ cy.get('#readMesh-mesh-details').should('contain', 'meshType')
+ })
+
+ it('Reads an mesh BinaryFile', function () {
+ cy.window().then(async (win) => {
+ const arrayBuffer = new Uint8Array(this['cow.vtk']).buffer
+ const { mesh, webWorker } = await win.meshIo.readMesh({ data: new Uint8Array(arrayBuffer), path: 'cow.vtk' })
+ webWorker.terminate()
+ verifyMesh(mesh)
+ })
+ })
+
+ it('Reads an mesh File', function () {
+ cy.window().then(async (win) => {
+ const arrayBuffer = new Uint8Array(this['cow.vtk']).buffer
+ const cowFile = new win.File([arrayBuffer], 'cow.vtk')
+ const { mesh, webWorker } = await win.meshIo.readMesh(cowFile)
+ webWorker.terminate()
+ verifyMesh(mesh)
+ })
+ })
+
+ it('Reads re-uses a WebWorker', function () {
+ cy.window().then(async (win) => {
+ const arrayBuffer = new Uint8Array(this['cow.vtk']).buffer
+ const cowFile = new win.File([arrayBuffer], 'cow.vtk')
+ const { webWorker } = await win.meshIo.readMesh(cowFile)
+ const { mesh } = await win.meshIo.readMesh(cowFile, { webWorker })
+ webWorker.terminate()
+ verifyMesh(mesh)
+ })
+ })
+
+ it('Throws a catchable error for an invalid file', { defaultCommandTimeout: 120000 }, function () {
+ cy.window().then(async (win) => {
+ const invalidArray = new Uint8Array([21, 4, 4, 4, 4, 9, 5, 0, 82, 42])
+ const invalidBlob = new win.Blob([invalidArray])
+ const invalidFile = new win.File([invalidBlob], 'invalid.file')
+ try {
+ const { webWorker, mesh } = await win.meshIo.readMesh(invalidFile)
+ webWorker.terminate()
+ } catch (error) {
+ cy.expect(error.message).to.equal('Could not find IO for: invalid.file')
+ }
+ })
+ })
+})
diff --git a/packages/transform-io/typescript/cypress/e2e/write-transform.cy.ts b/packages/transform-io/typescript/cypress/e2e/write-transform.cy.ts
new file mode 100644
index 000000000..389635247
--- /dev/null
+++ b/packages/transform-io/typescript/cypress/e2e/write-transform.cy.ts
@@ -0,0 +1,52 @@
+import { demoServer, verifyMesh } from "./common.ts";
+
+describe("write-mesh", () => {
+ beforeEach(function () {
+ cy.visit(demoServer);
+
+ const testPathPrefix = "../test/data/input/";
+
+ const testMeshFiles = ["cow.iwm.cbor"];
+ testMeshFiles.forEach((fileName) => {
+ cy.readFile(`${testPathPrefix}${fileName}`, null).as(fileName);
+ });
+ });
+
+ it("Writes an mesh in the demo", function () {
+ cy.get('sl-tab[panel="writeMesh-panel"]').click();
+
+ const testFile = {
+ contents: new Uint8Array(this["cow.iwm.cbor"]),
+ fileName: "cow.iwm.cbor",
+ };
+ cy.get('#writeMeshInputs input[name="mesh-file"]').selectFile([testFile], {
+ force: true,
+ });
+ cy.get("#writeMesh-mesh-details").should("contain", "meshType");
+ cy.get('#writeMeshInputs sl-input[name="serialized-mesh"]')
+ .find("input", { includeShadowDom: true })
+ .type("cow.vtk", { force: true });
+
+ cy.get('#writeMeshInputs sl-button[name="run"]').click();
+
+ cy.get("#writeMesh-serialized-mesh-details").should("contain", "35,32");
+ });
+
+ it("Writes an mesh to an ArrayBuffer", function () {
+ cy.window().then(async (win) => {
+ const arrayBuffer = new Uint8Array(this["cow.iwm.cbor"]).buffer;
+ const { mesh, webWorker } = await win.meshIo.readMesh({
+ data: new Uint8Array(arrayBuffer),
+ path: "cow.iwm.cbor",
+ });
+ const { serializedMesh } = await win.meshIo.writeMesh(mesh, "cow.vtk", {
+ webWorker,
+ });
+ const { mesh: meshBack } = await win.meshIo.readMesh(serializedMesh, {
+ webWorker,
+ });
+ webWorker.terminate();
+ verifyMesh(meshBack);
+ });
+ });
+});
diff --git a/packages/transform-io/typescript/cypress/support/commands.ts b/packages/transform-io/typescript/cypress/support/commands.ts
new file mode 100644
index 000000000..698b01a42
--- /dev/null
+++ b/packages/transform-io/typescript/cypress/support/commands.ts
@@ -0,0 +1,37 @@
+///
+// ***********************************************
+// This example commands.ts shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+//
+//
+// -- This is a parent command --
+// Cypress.Commands.add('login', (email, password) => { ... })
+//
+//
+// -- This is a child command --
+// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This will overwrite an existing command --
+// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
+//
+// declare global {
+// namespace Cypress {
+// interface Chainable {
+// login(email: string, password: string): Chainable
+// drag(subject: string, options?: Partial): Chainable
+// dismiss(subject: string, options?: Partial): Chainable
+// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable
+// }
+// }
+// }
\ No newline at end of file
diff --git a/packages/transform-io/typescript/cypress/support/e2e.ts b/packages/transform-io/typescript/cypress/support/e2e.ts
new file mode 100644
index 000000000..ca171c17d
--- /dev/null
+++ b/packages/transform-io/typescript/cypress/support/e2e.ts
@@ -0,0 +1,31 @@
+// ***********************************************************
+// This example support/e2e.ts is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands'
+
+// Alternatively you can use CommonJS syntax:
+// require('./commands')
+
+Cypress.on('uncaught:exception', (err, runnable) => {
+ // we expect a 3rd party library error with message 'list not defined'
+ // and don't want to fail the test so we return false
+ if (err.message.includes('ResizeObserver loop completed with undelivered notifications')) {
+ return false
+ }
+ // we still want to ensure there are no other unexpected
+ // errors, so we let them fail the test
+})
+
diff --git a/packages/transform-io/typescript/cypress/tsconfig.json b/packages/transform-io/typescript/cypress/tsconfig.json
new file mode 100644
index 000000000..212405809
--- /dev/null
+++ b/packages/transform-io/typescript/cypress/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "extends": "../tsconfig.json",
+ "include": [
+ "**/*.ts"
+ ],
+ "compilerOptions": {
+ "noEmit": false,
+ "sourceMap": false,
+ "inlineSourceMap": true,
+ "types": ["cypress"]
+ },
+}
diff --git a/packages/transform-io/typescript/package.json b/packages/transform-io/typescript/package.json
index a12f5ad0d..0bae2268e 100644
--- a/packages/transform-io/typescript/package.json
+++ b/packages/transform-io/typescript/package.json
@@ -15,8 +15,15 @@
},
"scripts": {
"start": "pnpm copyDemoAppAssets && vite",
- "test": "pnpm test:node",
+ "test": "pnpm test:node && pnpm test:browser",
"test:node": "ava",
+ "test:browser": "pnpm test:browser:chrome && pnpm test:browser:firefox",
+ "test:browser:firefox": "start-server-and-test start http-get://localhost:5181 cypress:runFirefox",
+ "test:browser:chrome": "start-server-and-test start http-get://localhost:5181 cypress:runChrome",
+ "test:browser:debug": "start-server-and-test start http-get://localhost:5181 cypress:open",
+ "cypress:open": "pnpm exec cypress open",
+ "cypress:runChrome": "pnpm exec cypress run --browser chrome",
+ "cypress:runFirefox": "pnpm exec cypress run --browser firefox",
"build": "pnpm build:tsc && pnpm build:browser:workerEmbedded && pnpm build:browser:workerEmbeddedMin && pnpm build:demo",
"build:browser:workerEmbedded": "esbuild --loader:.worker.js=dataurl --bundle --format=esm --outfile=./dist/bundle/index-worker-embedded.js ./src/index-worker-embedded.ts",
"build:browser:workerEmbeddedMin": "esbuild --minify --loader:.worker.js=dataurl --bundle --format=esm --outfile=./dist/bundle/index-worker-embedded.min.js ./src/index-worker-embedded.min.ts",
@@ -40,11 +47,13 @@
"devDependencies": {
"@itk-wasm/demo-app": "workspace:*",
"@itk-wasm/transform-io-build": "workspace:*",
- "@types/node": "^20.2.5",
"@types/mime-types": "^2.1.4",
+ "@types/node": "^20.2.5",
"ava": "^6.1.3",
+ "cypress": "^13.11.0",
"esbuild": "^0.19.8",
"shx": "^0.3.4",
+ "start-server-and-test": "^2.0.4",
"typescript": "^5.3.2",
"vite": "^4.5.0",
"vite-plugin-static-copy": "^0.17.0"
diff --git a/packages/transform-io/typescript/src/index-only.ts b/packages/transform-io/typescript/src/index-only.ts
index 080570398..c5805f984 100644
--- a/packages/transform-io/typescript/src/index-only.ts
+++ b/packages/transform-io/typescript/src/index-only.ts
@@ -1,125 +1,123 @@
-// Generated file. To retain edits, remove this comment.
+import ReadTransformResult from "./read-transform-result.js";
+export type { ReadTransformResult };
-export * from './pipelines-base-url.js'
-export * from './pipeline-worker-url.js'
-export * from './default-web-worker.js'
+import readTransform from "./read-transform.js";
+export { readTransform };
+import WriteTransformResult from "./write-transform-result.js";
+export type { WriteTransformResult };
-import Hdf5ReadTransformResult from './hdf5-read-transform-result.js'
-export type { Hdf5ReadTransformResult }
+import writeTransform from "./write-transform.js";
+export { writeTransform };
-import Hdf5ReadTransformOptions from './hdf5-read-transform-options.js'
-export type { Hdf5ReadTransformOptions }
+export * from "./pipelines-base-url.js";
+export * from "./pipeline-worker-url.js";
+export * from "./default-web-worker.js";
-import hdf5ReadTransform from './hdf5-read-transform.js'
-export { hdf5ReadTransform }
+import Hdf5ReadTransformResult from "./hdf5-read-transform-result.js";
+export type { Hdf5ReadTransformResult };
+import Hdf5ReadTransformOptions from "./hdf5-read-transform-options.js";
+export type { Hdf5ReadTransformOptions };
-import Hdf5WriteTransformResult from './hdf5-write-transform-result.js'
-export type { Hdf5WriteTransformResult }
+import hdf5ReadTransform from "./hdf5-read-transform.js";
+export { hdf5ReadTransform };
-import Hdf5WriteTransformOptions from './hdf5-write-transform-options.js'
-export type { Hdf5WriteTransformOptions }
+import Hdf5WriteTransformResult from "./hdf5-write-transform-result.js";
+export type { Hdf5WriteTransformResult };
-import hdf5WriteTransform from './hdf5-write-transform.js'
-export { hdf5WriteTransform }
+import Hdf5WriteTransformOptions from "./hdf5-write-transform-options.js";
+export type { Hdf5WriteTransformOptions };
+import hdf5WriteTransform from "./hdf5-write-transform.js";
+export { hdf5WriteTransform };
-import MatReadTransformResult from './mat-read-transform-result.js'
-export type { MatReadTransformResult }
+import MatReadTransformResult from "./mat-read-transform-result.js";
+export type { MatReadTransformResult };
-import MatReadTransformOptions from './mat-read-transform-options.js'
-export type { MatReadTransformOptions }
+import MatReadTransformOptions from "./mat-read-transform-options.js";
+export type { MatReadTransformOptions };
-import matReadTransform from './mat-read-transform.js'
-export { matReadTransform }
+import matReadTransform from "./mat-read-transform.js";
+export { matReadTransform };
+import MatWriteTransformResult from "./mat-write-transform-result.js";
+export type { MatWriteTransformResult };
-import MatWriteTransformResult from './mat-write-transform-result.js'
-export type { MatWriteTransformResult }
+import MatWriteTransformOptions from "./mat-write-transform-options.js";
+export type { MatWriteTransformOptions };
-import MatWriteTransformOptions from './mat-write-transform-options.js'
-export type { MatWriteTransformOptions }
+import matWriteTransform from "./mat-write-transform.js";
+export { matWriteTransform };
-import matWriteTransform from './mat-write-transform.js'
-export { matWriteTransform }
+import MncReadTransformResult from "./mnc-read-transform-result.js";
+export type { MncReadTransformResult };
+import MncReadTransformOptions from "./mnc-read-transform-options.js";
+export type { MncReadTransformOptions };
-import MncReadTransformResult from './mnc-read-transform-result.js'
-export type { MncReadTransformResult }
+import mncReadTransform from "./mnc-read-transform.js";
+export { mncReadTransform };
-import MncReadTransformOptions from './mnc-read-transform-options.js'
-export type { MncReadTransformOptions }
+import MncWriteTransformResult from "./mnc-write-transform-result.js";
+export type { MncWriteTransformResult };
-import mncReadTransform from './mnc-read-transform.js'
-export { mncReadTransform }
+import MncWriteTransformOptions from "./mnc-write-transform-options.js";
+export type { MncWriteTransformOptions };
+import mncWriteTransform from "./mnc-write-transform.js";
+export { mncWriteTransform };
-import MncWriteTransformResult from './mnc-write-transform-result.js'
-export type { MncWriteTransformResult }
+import TxtReadTransformResult from "./txt-read-transform-result.js";
+export type { TxtReadTransformResult };
-import MncWriteTransformOptions from './mnc-write-transform-options.js'
-export type { MncWriteTransformOptions }
+import TxtReadTransformOptions from "./txt-read-transform-options.js";
+export type { TxtReadTransformOptions };
-import mncWriteTransform from './mnc-write-transform.js'
-export { mncWriteTransform }
+import txtReadTransform from "./txt-read-transform.js";
+export { txtReadTransform };
+import TxtWriteTransformResult from "./txt-write-transform-result.js";
+export type { TxtWriteTransformResult };
-import TxtReadTransformResult from './txt-read-transform-result.js'
-export type { TxtReadTransformResult }
+import TxtWriteTransformOptions from "./txt-write-transform-options.js";
+export type { TxtWriteTransformOptions };
-import TxtReadTransformOptions from './txt-read-transform-options.js'
-export type { TxtReadTransformOptions }
+import txtWriteTransform from "./txt-write-transform.js";
+export { txtWriteTransform };
-import txtReadTransform from './txt-read-transform.js'
-export { txtReadTransform }
+import WasmReadTransformResult from "./wasm-read-transform-result.js";
+export type { WasmReadTransformResult };
+import WasmReadTransformOptions from "./wasm-read-transform-options.js";
+export type { WasmReadTransformOptions };
-import TxtWriteTransformResult from './txt-write-transform-result.js'
-export type { TxtWriteTransformResult }
+import wasmReadTransform from "./wasm-read-transform.js";
+export { wasmReadTransform };
-import TxtWriteTransformOptions from './txt-write-transform-options.js'
-export type { TxtWriteTransformOptions }
+import WasmWriteTransformResult from "./wasm-write-transform-result.js";
+export type { WasmWriteTransformResult };
-import txtWriteTransform from './txt-write-transform.js'
-export { txtWriteTransform }
+import WasmWriteTransformOptions from "./wasm-write-transform-options.js";
+export type { WasmWriteTransformOptions };
+import wasmWriteTransform from "./wasm-write-transform.js";
+export { wasmWriteTransform };
-import WasmReadTransformResult from './wasm-read-transform-result.js'
-export type { WasmReadTransformResult }
+import WasmZstdReadTransformResult from "./wasm-zstd-read-transform-result.js";
+export type { WasmZstdReadTransformResult };
-import WasmReadTransformOptions from './wasm-read-transform-options.js'
-export type { WasmReadTransformOptions }
+import WasmZstdReadTransformOptions from "./wasm-zstd-read-transform-options.js";
+export type { WasmZstdReadTransformOptions };
-import wasmReadTransform from './wasm-read-transform.js'
-export { wasmReadTransform }
+import wasmZstdReadTransform from "./wasm-zstd-read-transform.js";
+export { wasmZstdReadTransform };
+import WasmZstdWriteTransformResult from "./wasm-zstd-write-transform-result.js";
+export type { WasmZstdWriteTransformResult };
-import WasmWriteTransformResult from './wasm-write-transform-result.js'
-export type { WasmWriteTransformResult }
+import WasmZstdWriteTransformOptions from "./wasm-zstd-write-transform-options.js";
+export type { WasmZstdWriteTransformOptions };
-import WasmWriteTransformOptions from './wasm-write-transform-options.js'
-export type { WasmWriteTransformOptions }
-
-import wasmWriteTransform from './wasm-write-transform.js'
-export { wasmWriteTransform }
-
-
-import WasmZstdReadTransformResult from './wasm-zstd-read-transform-result.js'
-export type { WasmZstdReadTransformResult }
-
-import WasmZstdReadTransformOptions from './wasm-zstd-read-transform-options.js'
-export type { WasmZstdReadTransformOptions }
-
-import wasmZstdReadTransform from './wasm-zstd-read-transform.js'
-export { wasmZstdReadTransform }
-
-
-import WasmZstdWriteTransformResult from './wasm-zstd-write-transform-result.js'
-export type { WasmZstdWriteTransformResult }
-
-import WasmZstdWriteTransformOptions from './wasm-zstd-write-transform-options.js'
-export type { WasmZstdWriteTransformOptions }
-
-import wasmZstdWriteTransform from './wasm-zstd-write-transform.js'
-export { wasmZstdWriteTransform }
+import wasmZstdWriteTransform from "./wasm-zstd-write-transform.js";
+export { wasmZstdWriteTransform };
diff --git a/packages/transform-io/typescript/src/read-transform-result.ts b/packages/transform-io/typescript/src/read-transform-result.ts
new file mode 100644
index 000000000..72615842c
--- /dev/null
+++ b/packages/transform-io/typescript/src/read-transform-result.ts
@@ -0,0 +1,8 @@
+import { TransformList } from "itk-wasm";
+
+interface ReadTransformResult {
+ transform: TransformList;
+ webWorker: Worker;
+}
+
+export default ReadTransformResult;
diff --git a/packages/transform-io/typescript/src/read-transform.ts b/packages/transform-io/typescript/src/read-transform.ts
new file mode 100644
index 000000000..01a35dc3a
--- /dev/null
+++ b/packages/transform-io/typescript/src/read-transform.ts
@@ -0,0 +1,112 @@
+import {
+ BinaryFile,
+ TransformList,
+ getFileExtension,
+ WorkerPoolFunctionResult,
+ WorkerPoolFunctionOption,
+} from "itk-wasm";
+
+import mimeToTransformIo from "./mime-to-transform-io.js";
+import extensionToTransformIo from "./extension-to-transform-io.js";
+import transformIoIndex from "./transform-io-index.js";
+
+import ReadTransformOptions from "./read-transform-options.js";
+import ReadTransformResult from "./read-transform-result.js";
+
+interface ReaderResult extends WorkerPoolFunctionResult {
+ couldRead: boolean;
+ transform: TransformList;
+}
+interface ReaderOptions extends WorkerPoolFunctionOption {
+ /** Use float for the parameters value type. The default is double. */
+ floatParameters?: boolean;
+}
+type Reader = (
+ serializedTransform: File | BinaryFile,
+ options: ReaderOptions
+) => Promise;
+
+/**
+ * Read a transform file format and convert it to the ITK-Wasm file format
+ *
+ * @param {webWorker} null | webWorker - Web worker to run the pipeline or null to run it in a new worker
+ * @param {File | BinaryFile} serializedTransform - Input transform serialized in the file format
+ * @param {ReadTransformOptions} options - options to cast the resulting transform type or to only read transform metadata
+ *
+ * @returns {Promise} - result object with the transform and the web worker used
+ */
+async function readTransform(
+ serializedTransform: File | BinaryFile,
+ options: ReadTransformOptions = {}
+): Promise {
+ const mimeType = (serializedTransform as File).type ?? "";
+ const fileName =
+ (serializedTransform as File).name ??
+ (serializedTransform as BinaryFile).path ??
+ "fileName";
+ const extension = getFileExtension(fileName).toLowerCase();
+ let usedWebWorker = options?.webWorker;
+
+ let serializedTransformFile = serializedTransform as BinaryFile;
+ if (serializedTransform instanceof Blob) {
+ const serializedTransformBuffer = await serializedTransform.arrayBuffer();
+ serializedTransformFile = {
+ path: serializedTransform.name,
+ data: new Uint8Array(serializedTransformBuffer),
+ };
+ }
+
+ let io = null;
+ if (mimeType && mimeToTransformIo.has(mimeType)) {
+ io = mimeToTransformIo.get(mimeType);
+ } else if (extensionToTransformIo.has(extension)) {
+ io = extensionToTransformIo.get(extension);
+ } else {
+ for (const readerWriter of transformIoIndex.values()) {
+ if (readerWriter[0] !== null) {
+ let {
+ webWorker: testWebWorker,
+ couldRead,
+ transform,
+ } = await (readerWriter[0] as unknown as Reader)(
+ {
+ path: serializedTransformFile.path,
+ data: serializedTransformFile.data.slice(),
+ },
+ {
+ floatParameters: options.floatParameters,
+ webWorker: usedWebWorker,
+ noCopy: options?.noCopy,
+ }
+ );
+ usedWebWorker = testWebWorker;
+ if (couldRead) {
+ return { webWorker: usedWebWorker, transform };
+ }
+ }
+ }
+ }
+ if (!io) {
+ throw Error("Could not find IO for: " + fileName);
+ }
+ const readerWriter = transformIoIndex.get(io as string);
+
+ const reader = (readerWriter as Array)[0];
+ let {
+ webWorker: testWebWorker,
+ couldRead,
+ transform,
+ } = await reader(serializedTransformFile, {
+ floatParameters: options.floatParameters,
+ webWorker: usedWebWorker,
+ noCopy: options?.noCopy,
+ });
+ usedWebWorker = testWebWorker;
+ if (!couldRead) {
+ throw Error("Could not read: " + fileName);
+ }
+
+ return { webWorker: usedWebWorker, transform };
+}
+
+export default readTransform;
diff --git a/packages/transform-io/typescript/src/transform-io-index.ts b/packages/transform-io/typescript/src/transform-io-index.ts
new file mode 100644
index 000000000..80c9b3596
--- /dev/null
+++ b/packages/transform-io/typescript/src/transform-io-index.ts
@@ -0,0 +1,23 @@
+import hdf5ReadTransform from "./hdf5-read-transform.js";
+import hdf5WriteTransform from "./hdf5-write-transform.js";
+import matReadTransform from "./mat-read-transform.js";
+import matWriteTransform from "./mat-write-transform.js";
+import mncReadTransform from "./mnc-read-transform.js";
+import mncWriteTransform from "./mnc-write-transform.js";
+import txtReadTransform from "./txt-read-transform.js";
+import txtWriteTransform from "./txt-write-transform.js";
+import wasmReadTransform from "./wasm-read-transform.js";
+import wasmWriteTransform from "./wasm-write-transform.js";
+import wasmZstdReadTransform from "./wasm-zstd-read-transform.js";
+import wasmZstdWriteTransform from "./wasm-zstd-write-transform.js";
+
+const transformIoIndex = new Map([
+ ["hdf5", [hdf5ReadTransform, hdf5WriteTransform]],
+ ["mat", [matReadTransform, matWriteTransform]],
+ ["mnc", [mncReadTransform, mncWriteTransform]],
+ ["txt", [txtReadTransform, txtWriteTransform]],
+ ["wasm", [wasmReadTransform, wasmWriteTransform]],
+ ["wasmZstd", [wasmZstdReadTransform, wasmZstdWriteTransform]],
+]);
+
+export default transformIoIndex;
diff --git a/packages/transform-io/typescript/src/write-transform-node.ts b/packages/transform-io/typescript/src/write-transform-node.ts
index 84b7c2509..d87a7f498 100644
--- a/packages/transform-io/typescript/src/write-transform-node.ts
+++ b/packages/transform-io/typescript/src/write-transform-node.ts
@@ -69,8 +69,6 @@ async function writeTransformNode(
const readerWriter = transformIoIndexNode.get(io as string);
const writer = (readerWriter as Array)[1];
- console.log("writer", writer);
- console.log("inputTransform", inputTransform);
let { couldWrite } = await writer(inputTransform, absoluteFilePath, {
useCompression: options.useCompression,
});
diff --git a/packages/transform-io/typescript/src/write-transform-result.ts b/packages/transform-io/typescript/src/write-transform-result.ts
new file mode 100644
index 000000000..ca4efc71e
--- /dev/null
+++ b/packages/transform-io/typescript/src/write-transform-result.ts
@@ -0,0 +1,11 @@
+import { BinaryFile } from "itk-wasm";
+
+interface WriteTransformResult {
+ /** WebWorker used for computation */
+ webWorker: Worker | null;
+
+ /** Output image serialized in the file format. */
+ serializedTransform: BinaryFile;
+}
+
+export default WriteTransformResult;
diff --git a/packages/transform-io/typescript/src/write-transform.ts b/packages/transform-io/typescript/src/write-transform.ts
new file mode 100644
index 000000000..6638c0374
--- /dev/null
+++ b/packages/transform-io/typescript/src/write-transform.ts
@@ -0,0 +1,96 @@
+import { TransformList, BinaryFile, getFileExtension } from "itk-wasm";
+
+import mimeToTransformIo from "./mime-to-transform-io.js";
+import extensionToTransformIo from "./extension-to-transform-io.js";
+import transformIoIndex from "./transform-io-index.js";
+import WriteTransformOptions from "./write-transform-options.js";
+import WriteTransformResult from "./write-transform-result.js";
+
+interface WriterOptions {
+ floatParameters?: boolean;
+ useCompression?: boolean;
+ /** WebWorker for computation. Set to null to create a new worker. Or, pass an existing worker. Or, set to `false` to run in the current thread / worker. */
+ webWorker?: Worker | null | boolean;
+}
+interface WriterResult {
+ webWorker: Worker;
+ couldWrite: boolean;
+ serializedTransform: BinaryFile;
+}
+type Writer = (
+ transform: TransformList,
+ serializedTransform: string,
+ options: WriterOptions
+) => Promise;
+
+/**
+ * Write an ITK-Wasm TransformList converted to an serialized transform file format
+ *
+ * @param {TransformList} transform - Input transform
+ * @param {string} serializedTransform - Output transform serialized in the file format.
+ * @param {WriteTransformOptions} options - options object
+ *
+ * @returns {Promise} - result object
+ */
+async function writeTransform(
+ transform: TransformList,
+ serializedTransform: string,
+ options: WriteTransformOptions = {}
+): Promise {
+ let inputTransform = transform;
+
+ const mimeType = options.mimeType;
+ const extension = getFileExtension(serializedTransform).toLowerCase();
+ let usedWebWorker = options.webWorker;
+
+ let io = null;
+ if (typeof mimeType !== "undefined" && mimeToTransformIo.has(mimeType)) {
+ io = mimeToTransformIo.get(mimeType);
+ } else if (extensionToTransformIo.has(extension)) {
+ io = extensionToTransformIo.get(extension);
+ } else {
+ for (const readerWriter of transformIoIndex.values()) {
+ if (readerWriter[1] !== null) {
+ let {
+ webWorker: testWebWorker,
+ couldWrite,
+ serializedTransform: serializedTransformBuffer,
+ } = await (readerWriter[1] as unknown as Writer)(
+ inputTransform,
+ serializedTransform,
+ options
+ );
+ usedWebWorker = testWebWorker;
+ if (couldWrite) {
+ return {
+ webWorker: usedWebWorker as Worker,
+ serializedTransform: serializedTransformBuffer,
+ };
+ }
+ }
+ }
+ }
+ if (!io) {
+ throw Error("Could not find IO for: " + serializedTransform);
+ }
+ const readerWriter = transformIoIndex.get(io as string);
+
+ const writer = (readerWriter as Array)[1];
+ let {
+ webWorker: testWebWorker,
+ couldWrite,
+ serializedTransform: serializedTransformBuffer,
+ } = await writer(inputTransform, serializedTransform, options);
+ usedWebWorker = testWebWorker;
+ if (!couldWrite) {
+ throw Error("Could not write: " + serializedTransform);
+ }
+
+ const result = {
+ webWorker: usedWebWorker as Worker,
+ serializedTransform: serializedTransformBuffer,
+ };
+ return result;
+}
+
+export default writeTransform;
diff --git a/packages/transform-io/typescript/vite.config.js b/packages/transform-io/typescript/vite.config.js
index eb915742e..e07ca6410 100644
--- a/packages/transform-io/typescript/vite.config.js
+++ b/packages/transform-io/typescript/vite.config.js
@@ -1,30 +1,45 @@
-import { defineConfig } from 'vite'
-import { viteStaticCopy } from 'vite-plugin-static-copy'
-import path from 'path'
+import { defineConfig } from "vite";
+import { viteStaticCopy } from "vite-plugin-static-copy";
+import path from "path";
-const base = process.env.VITE_BASE_URL || '/'
+const base = process.env.VITE_BASE_URL || "/";
export default defineConfig({
- root: path.join('test', 'browser', 'demo-app'),
+ root: path.join("test", "browser", "demo-app"),
base,
+ server: {
+ port: 5181,
+ },
build: {
- outDir: '../../../demo-app',
+ outDir: "../../../demo-app",
emptyOutDir: true,
},
worker: {
- format: 'es'
+ format: "es",
},
optimizeDeps: {
- exclude: ['itk-wasm', '@itk-wasm/image-io', '@itk-wasm/mesh-io', '@thewtex/zstddec', '@itk-viewer/io']
+ exclude: [
+ "itk-wasm",
+ "@itk-wasm/image-io",
+ "@itk-wasm/mesh-io",
+ "@thewtex/zstddec",
+ "@itk-viewer/io",
+ ],
},
plugins: [
// put lazy loaded JavaScript and Wasm bundles in dist directory
viteStaticCopy({
targets: [
- { src: '../../../dist/pipelines/*', dest: 'pipelines' },
- { src: '../../../node_modules/@itk-wasm/image-io/dist/pipelines/*.{js,wasm,wasm.zst}', dest: 'pipelines' },
- { src: '../../../node_modules/@itk-wasm/mesh-io/dist/pipelines/*.{js,wasm,wasm.zst}', dest: 'pipelines' },
+ { src: "../../../dist/pipelines/*", dest: "pipelines" },
+ {
+ src: "../../../node_modules/@itk-wasm/image-io/dist/pipelines/*.{js,wasm,wasm.zst}",
+ dest: "pipelines",
+ },
+ {
+ src: "../../../node_modules/@itk-wasm/mesh-io/dist/pipelines/*.{js,wasm,wasm.zst}",
+ dest: "pipelines",
+ },
],
- })
+ }),
],
-})
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7d35c7ec9..7d4f3ce3d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -787,12 +787,18 @@ importers:
ava:
specifier: ^6.1.3
version: 6.1.3
+ cypress:
+ specifier: ^13.11.0
+ version: 13.11.0
esbuild:
specifier: ^0.19.8
version: 0.19.12
shx:
specifier: ^0.3.4
version: 0.3.4
+ start-server-and-test:
+ specifier: ^2.0.4
+ version: 2.0.4
typescript:
specifier: ^5.3.2
version: 5.4.5