From 1034b3fea3681d8c751dab1f62d3d71c7230c4f1 Mon Sep 17 00:00:00 2001 From: hamed musallam Date: Thu, 23 Nov 2023 19:11:23 +0100 Subject: [PATCH] refactor: combine the functionality of nmr-snapshot-cli with nmr-cli and remove nmr-snapshot-cli3 --- app/scripts/nmr-cli/Dockerfile | 10 +- app/scripts/nmr-cli/bin/index.js | 180 +++++++++++++++++----- app/scripts/nmr-cli/package-lock.json | 76 +++++++-- app/scripts/nmr-cli/package.json | 7 +- app/scripts/nmr-snapshot-cli/Dockerfile | 24 --- app/scripts/nmr-snapshot-cli/bin/index.js | 144 ----------------- app/scripts/nmr-snapshot-cli/package.json | 21 --- docker-compose.yml | 5 - 8 files changed, 209 insertions(+), 258 deletions(-) delete mode 100644 app/scripts/nmr-snapshot-cli/Dockerfile delete mode 100755 app/scripts/nmr-snapshot-cli/bin/index.js delete mode 100644 app/scripts/nmr-snapshot-cli/package.json diff --git a/app/scripts/nmr-cli/Dockerfile b/app/scripts/nmr-cli/Dockerfile index 7aaf2e9..a6b0393 100644 --- a/app/scripts/nmr-cli/Dockerfile +++ b/app/scripts/nmr-cli/Dockerfile @@ -1,15 +1,19 @@ # build the image ` docker build --tag nmr-cli . ` # run the container ` docker run -it nmr-cli bash ` -FROM node:20.9.0-alpine -# a temporary command to add bash to the Docker image to be able to run the container with an interactive Shell for testing purpose -RUN apk update && apk add bash +FROM mcr.microsoft.com/playwright:v1.40.0-jammy + SHELL ["/bin/bash", "-o", "pipefail", "-c"] WORKDIR /app +#ENV BASE_NMRIUM_URL=https://nmrium.nmrxiv.org/ +ENV BASE_NMRIUM_URL=https://nmriumdev.nmrxiv.org/ + + COPY package.json ./ COPY package-lock.json ./ + RUN npm install COPY . ./ diff --git a/app/scripts/nmr-cli/bin/index.js b/app/scripts/nmr-cli/bin/index.js index 7556d97..8f3dc07 100755 --- a/app/scripts/nmr-cli/bin/index.js +++ b/app/scripts/nmr-cli/bin/index.js @@ -1,64 +1,162 @@ #!/usr/bin/env node -const {join,isAbsolute}= require("path"); +const { join, isAbsolute } = require("path"); const yargs = require("yargs"); const loader = require("nmr-load-save"); const fileUtils = require("filelist-utils"); +const playwright = require('playwright'); -const usageMessage ="Usage: nmr-cli -u or -p " +const usageMessage = "Usage: nmr-cli -u or -p -s" + + +/** + * How to Use the Command Line Tool: + * Example 1: Process spectra files from a URL + * Usage: nmr-cli -u https://example.com/file.zip + * ------------------------------------------------------------------------- + * Example 2: process a spectra files from a directory < nmr-cli -p /path/to/directory > + * Usage: nmr-cli -p /path/to/directory + * ------------------------------------------------------------------------- + * you could also combine the above examples with an optional parameter to capturing a snapshot using the -s option + * + */ const options = yargs - .usage(usageMessage) - .option("u", { alias: "url", describe: "File URL", type: "string",nargs:1}) - .option("p", { alias: "path", describe: "Directory path", type: "string",nargs:1}).showHelpOnFail(); - - async function loadSpectrumFromURL(url) { - const {pathname:relativePath,origin:baseURL} = new URL(url); - const source = { - entries: [ - { - relativePath, - } - ], - baseURL - }; - const fileCollection = await fileUtils.fileCollectionFromWebSource(source,{}); - - const { - nmriumState: { data }, - } = await loader.read(fileCollection); - return data; + .usage(usageMessage) + .option("u", { alias: "url", describe: "File URL", type: "string", nargs: 1 }) + .option("p", { alias: "path", describe: "Directory path", type: "string", nargs: 1 }) + .option("s", { alias: "capture-snapshot", describe: "Capture snapshot", type: "boolean" }).showHelpOnFail(); + + + + +function generateNMRiumURL() { + const baseURL = process.env['BASE_NMRIUM_URL']; + const url = new URL(baseURL) + url.searchParams.append('workspace', "embedded") + return url.toString() +} + +async function captureSpectraViewAsBase64(nmriumState) { + const { data: { spectra }, version } = nmriumState; + const browser = await playwright.chromium.launch() + const context = await browser.newContext(playwright.devices['Desktop Chrome HiDPI']) + const page = await context.newPage() + + const url = generateNMRiumURL() + + await page.goto(url) + + await page.locator('text=Loading').waitFor({ state: 'hidden' }); + + let snapshots = [] + + for (const spectrum of spectra || []) { + const spectrumObject = { + version, + data: { + spectra: [{ ...spectrum }], + } + + } + + // convert typed array to array + const stringObject = JSON.stringify(spectrumObject, (key, value) => { + return ArrayBuffer.isView(value) ? Array.from(value) : value + }) + + // load the spectrum into NMRium using the custom event + await page.evaluate( + ` + window.postMessage({ type: "nmr-wrapper:load", data:{data: ${stringObject},type:"nmrium"}}, '*'); + ` + ) + + //wait for NMRium process and load spectra + await page.locator('text=Loading').waitFor({ state: 'hidden' }); + + // take a snapshot for the spectrum + try { + const snapshot = await page.locator('#nmrSVG .container').screenshot() + + snapshots.push({ + image: snapshot.toString('base64'), + id: spectrum.id, + }) + } catch (e) { + console.log(e) + } } + await context.close() + await browser.close() + + return snapshots; +} - async function loadSpectrumFromFilePath(path) { - const dirPath = isAbsolute(path)?path:join(process.cwd(),path) - - const fileCollection = await fileUtils.fileCollectionFromPath(dirPath,{}); - - const { - nmriumState: { data }, - } = await loader.read(fileCollection); - return data; +async function loadSpectrumFromURL(url, enableSnapshot = false) { + const { pathname: relativePath, origin: baseURL } = new URL(url); + const source = { + entries: [ + { + relativePath, + } + ], + baseURL + }; + const fileCollection = await fileUtils.fileCollectionFromWebSource(source, {}); + + const { + nmriumState: { data, version }, + } = await loader.read(fileCollection); + + let images = [] + + if (enableSnapshot) { + images = await captureSpectraViewAsBase64({ data, version }); } - const parameters = options.argv; + return { data, version, images }; +} + + +async function loadSpectrumFromFilePath(path, enableSnapshot = false) { + const dirPath = isAbsolute(path) ? path : join(process.cwd(), path) + + const fileCollection = await fileUtils.fileCollectionFromPath(dirPath, {}); + + const { + nmriumState: { data, version } + } = await loader.read(fileCollection); + + let images = [] -if(parameters.u && parameters.p){ + if (enableSnapshot) { + images = await captureSpectraViewAsBase64({ data, version }); + } + + + return { data, version, images }; +} + + +const parameters = options.argv; + +if (parameters.u && parameters.p) { options.showHelp(); -}else{ +} else { - if(parameters.u){ - loadSpectrumFromURL(parameters.u).then((result)=>{ - console.log(JSON.stringify(result)) - }) + if (parameters.u) { + loadSpectrumFromURL(parameters.u, parameters.s).then((result) => { + console.log(JSON.stringify(result)) + }) } - if(parameters.p){ - loadSpectrumFromFilePath(parameters.p).then((result)=>{ + if (parameters.p) { + loadSpectrumFromFilePath(parameters.p, parameters.s).then((result) => { console.log(JSON.stringify(result)) - }) + }) } } diff --git a/app/scripts/nmr-cli/package-lock.json b/app/scripts/nmr-cli/package-lock.json index f93a607..9e87805 100644 --- a/app/scripts/nmr-cli/package-lock.json +++ b/app/scripts/nmr-cli/package-lock.json @@ -10,7 +10,8 @@ "license": "ISC", "dependencies": { "filelist-utils": "^1.10.2", - "nmr-load-save": "^0.22.4", + "nmr-load-save": "^0.23.3", + "playwright": "^1.40.0", "yargs": "^17.7.2" }, "bin": { @@ -256,6 +257,19 @@ "node": ">= 6" } }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -276,9 +290,9 @@ } }, "node_modules/gyromagnetic-ratio": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gyromagnetic-ratio/-/gyromagnetic-ratio-1.0.0.tgz", - "integrity": "sha512-s55NtJPxoplsW/8OnM1C7tNWd2gEXXt+roF3NPNDKFb7YchBy9JXdxmzztf3d4JL1zCiQz5cn6HSC8M0osN78w==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gyromagnetic-ratio/-/gyromagnetic-ratio-1.1.1.tgz", + "integrity": "sha512-M1y9bAhK11moqAPRZ5oUoDCEIQCogjKYXDMlkXJiSjkLFmOAp1qevrjThF+6KrtwkSpmT7Vgy8C/mgBlIdZPSg==" }, "node_modules/heap": { "version": "0.2.7", @@ -343,14 +357,14 @@ } }, "node_modules/jcampconverter": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/jcampconverter/-/jcampconverter-9.2.2.tgz", - "integrity": "sha512-+mZK6QzbwnDBorK6lzccFuBNiTSGgwQGKczdhxNzpYjKS1osEQwtmgPJVEp9JGqbI7ClxXJU6IAyxivIBN/jLA==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/jcampconverter/-/jcampconverter-9.5.0.tgz", + "integrity": "sha512-xsuZXcUd+YkF0Rlt0IZa1+4XbMYq/fR6+gewwDJd5M17y2+SbjrgESKZH73+GokzLC7H1KTS0/l5/7cQFFLgiA==", "dependencies": { "cheminfo-types": "^1.7.2", "dynamic-typing": "^1.0.0", "ensure-string": "^1.2.0", - "gyromagnetic-ratio": "^1.0.0", + "gyromagnetic-ratio": "^1.1.1", "ml-array-median": "^1.1.6" } }, @@ -717,9 +731,9 @@ } }, "node_modules/nmr-load-save": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/nmr-load-save/-/nmr-load-save-0.22.4.tgz", - "integrity": "sha512-U3HAOz67ilLKLKoCKVQciGma8e/FPE9bM/J9k+1BJEU+JgmWuLPt4bqIoGz8E2A5huvKD1/JW38SrMXZvOWCVg==", + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/nmr-load-save/-/nmr-load-save-0.23.5.tgz", + "integrity": "sha512-dpBGXvQCaCnblvo87ILf4AkFfNg2BYtgVGZPoBqvS2O8uQbKwL5tUNep9peyVF336nvRrzzfkIih1bTpYu4BPQ==", "dependencies": { "@lukeed/uuid": "^2.0.1", "@types/lodash.merge": "^4.6.7", @@ -727,14 +741,14 @@ "cheminfo-types": "^1.7.2", "convert-to-jcamp": "^5.4.9", "filelist-utils": "^1.10.2", - "gyromagnetic-ratio": "^1.0.0", + "gyromagnetic-ratio": "^1.1.0", "is-any-array": "^2.0.1", - "jcampconverter": "^9.2.2", + "jcampconverter": "^9.5.0", "jeolconverter": "^1.0.2", "lodash.merge": "^4.6.2", "ml-spectra-processing": "^12.5.1", "nmr-correlation": "^2.3.3", - "nmr-processing": "^11.4.1", + "nmr-processing": "^11.6.0", "nmredata": "^0.9.7", "openchemlib": "^8.7.0", "openchemlib-utils": "^5.4.0", @@ -743,9 +757,9 @@ } }, "node_modules/nmr-processing": { - "version": "11.4.1", - "resolved": "https://registry.npmjs.org/nmr-processing/-/nmr-processing-11.4.1.tgz", - "integrity": "sha512-pA/Z5vWcQcetaB3UHip0+XahjNQh7c9JPAE9uC+HHpRoagb13U4cnO4RLApdxOTKzjKwsXC4sSwtZKqJbpES4A==", + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/nmr-processing/-/nmr-processing-11.6.0.tgz", + "integrity": "sha512-Hqh3h3WYlZNTuXODgd7LJh7Qt04pHb4gJedpcZoex8f7wL6vyWsAF7F85KwXDCrsZ4nEGPxh5a004VYZdVEHSg==", "dependencies": { "@lukeed/uuid": "^2.0.1", "binary-search": "^1.3.6", @@ -857,6 +871,34 @@ "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" }, + "node_modules/playwright": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", + "integrity": "sha512-gyHAgQjiDf1m34Xpwzaqb76KgfzYrhK7iih+2IzcOCoZWr/8ZqmdBw+t0RU85ZmfJMgtgAiNtBQ/KS2325INXw==", + "dependencies": { + "playwright-core": "1.40.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.0.tgz", + "integrity": "sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", diff --git a/app/scripts/nmr-cli/package.json b/app/scripts/nmr-cli/package.json index 6ffddf1..64eb68a 100644 --- a/app/scripts/nmr-cli/package.json +++ b/app/scripts/nmr-cli/package.json @@ -14,7 +14,8 @@ }, "dependencies": { "filelist-utils": "^1.10.2", - "nmr-load-save": "^0.22.4", - "yargs": "^17.7.2" + "nmr-load-save": "^0.23.3", + "yargs": "^17.7.2", + "playwright": "^1.40.0" } -} +} \ No newline at end of file diff --git a/app/scripts/nmr-snapshot-cli/Dockerfile b/app/scripts/nmr-snapshot-cli/Dockerfile deleted file mode 100644 index aef252e..0000000 --- a/app/scripts/nmr-snapshot-cli/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -# build the image ` docker build --tag nmr-snapshot-cli . ` -# run the container ` docker run -it nmr-snapshot-cli bash ` - -FROM mcr.microsoft.com/playwright:v1.40.0-jammy - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] - -WORKDIR /app - -#ENV BASE_NMRIUM_URL=https://nmrium.nmrxiv.org/ -ENV BASE_NMRIUM_URL=https://nmriumdev.nmrxiv.org/ - -COPY package.json ./ - -RUN npm i - -COPY . ./ - -#install the nmr-snapshot-cli as a global package -#example, nmr-snapshot-cli -u https://cheminfo.github.io/bruker-data-test/data/zipped/aspirin-1h.zip -RUN npm install . -g - - - diff --git a/app/scripts/nmr-snapshot-cli/bin/index.js b/app/scripts/nmr-snapshot-cli/bin/index.js deleted file mode 100755 index 275d8fa..0000000 --- a/app/scripts/nmr-snapshot-cli/bin/index.js +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env node -const { join, isAbsolute } = require("path"); -const yargs = require("yargs"); -const loader = require("nmr-load-save"); -const fileUtils = require("filelist-utils"); -const playwright = require('playwright'); - -const usageMessage = "Usage: nmr-snapshot-cli -u or -p " - -const options = yargs - .usage(usageMessage) - .option("u", { alias: "url", describe: "File URL", type: "string", nargs: 1 }) - .option("p", { alias: "path", describe: "Directory path", type: "string", nargs: 1 }).showHelpOnFail(); - - -const PARSING_OPTIONS = { - onLoadProcessing: { autoProcessing: true }, - sourceSelector: { general: { dataSelection: 'preferFT' } }, -} - - -function generateNMRiumURL() { - const baseURL = process.env['BASE_NMRIUM_URL']; - const url = new URL(baseURL) - url.searchParams.append('workspace', "embedded") - return url.toString() -} - -async function getSpectraViewAsBase64(nmriumState) { - const { data: { spectra }, version } = nmriumState; - const browser = await playwright.chromium.launch() - const context = await browser.newContext(playwright.devices['Desktop Chrome HiDPI']) - const page = await context.newPage() - - const url = generateNMRiumURL() - - await page.goto(url) - - await page.locator('text=Loading').waitFor({ state: 'hidden' }); - - let snapshots = [] - - for (const spectrum of spectra || []) { - const spectrumObject = { - version, - data: { - spectra: [{ ...spectrum }], - } - - } - - // convert typed array to array - const stringObject = JSON.stringify(spectrumObject, (key, value) => { - return ArrayBuffer.isView(value) ? Array.from(value) : value - }) - - // load the spectrum into NMRium using the custom event - await page.evaluate( - ` - window.postMessage({ type: "nmr-wrapper:load", data:{data: ${stringObject},type:"nmrium"}}, '*'); - ` - ) - - //wait for NMRium process and load spectra - await page.locator('text=Loading').waitFor({ state: 'hidden' }); - - // take a snapshot for the spectrum - try { - const snapshot = await page.locator('#nmrSVG .container').screenshot() - - snapshots.push({ - image: snapshot.toString('base64'), - id: spectrum.id, - }) - } catch (e) { - console.log(e) - } - } - - await context.close() - await browser.close() - - return snapshots; -} - - -async function captureSpectrumSnapshotFromURL(url) { - const { pathname: relativePath, origin: baseURL } = new URL(url); - const source = { - entries: [ - { - relativePath, - } - ], - baseURL - }; - const fileCollection = await fileUtils.fileCollectionFromWebSource(source, {}); - - const { - nmriumState - } = await loader.read(fileCollection, PARSING_OPTIONS); - - - return getSpectraViewAsBase64(nmriumState); -} - - -async function captureSpectrumSnapshotFromFilePath(path) { - const dirPath = isAbsolute(path) ? path : join(process.cwd(), path) - - const fileCollection = await fileUtils.fileCollectionFromPath(dirPath, {}); - - const { - nmriumState - } = await loader.read(fileCollection, PARSING_OPTIONS); - return getSpectraViewAsBase64(nmriumState); -} - - -const parameters = options.argv; - -if (parameters.u && parameters.p) { - options.showHelp(); -} else { - - if (parameters.u) { - captureSpectrumSnapshotFromURL(parameters.u).then((result) => { - console.log(JSON.stringify(result)) - }) - - } - - if (parameters.p) { - captureSpectrumSnapshotFromFilePath(parameters.p).then((result) => { - console.log(JSON.stringify(result)) - }) - } - -} - - - - - diff --git a/app/scripts/nmr-snapshot-cli/package.json b/app/scripts/nmr-snapshot-cli/package.json deleted file mode 100644 index 7076e1c..0000000 --- a/app/scripts/nmr-snapshot-cli/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "test-node", - "version": "1.0.0", - "description": "", - "main": "bin/index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "bin": { - "nmr-snapshot-cli": "./bin/index.js" - }, - "dependencies": { - "filelist-utils": "^1.10.2", - "nmr-load-save": "^0.23.3", - "playwright": "^1.40.0", - "yargs": "^17.7.2" - } -} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 544a02e..a36d7f0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,11 +37,6 @@ services: entrypoint: /bin/sh stdin_open: true tty: true - nmr-snapshot: - build: ./app/scripts/nmr-snapshot-cli - entrypoint: /bin/sh - stdin_open: true - tty: true prometheus: image: prom/prometheus container_name: nmrkit_prometheus