diff --git a/model/src/helpers.ts b/model/src/helpers.ts index e2ad97e..8255f32 100644 --- a/model/src/helpers.ts +++ b/model/src/helpers.ts @@ -4,6 +4,7 @@ import { z } from 'zod'; import { base32Encode } from './base32-encode'; +import { PValueInt, TreeNodeAccessor } from '@milaboratory/sdk-ui'; /** Number of raw bytes in the PlId. */ export const PlIdBytes = 15; @@ -33,3 +34,66 @@ export async function digestPlId(data: string): Promise { const bytes = await crypto.subtle.digest('SHA-256', encoder.encode(data)); return plId(new Uint8Array(bytes.slice(0, 15))); } + +export const ResourceMapResourceTypeName = 'PColumnData/ResourceMap'; +export const ResourceMapResourcePartitionedTypeName = 'PColumnData/Partitioned/ResourceMap'; + +export type PColumnKey = (string | number)[]; + +export type PColumnResourceMapEntry = { + key: PColumnKey; + value: T; +}; + +export type PColumnResourceMapData = { + isComplete: boolean; + data: PColumnResourceMapEntry[]; +}; + +function populateResourceMapData( + acc: TreeNodeAccessor | undefined, + resourceParser: (acc: TreeNodeAccessor) => T | undefined, + data: PColumnResourceMapEntry[], + keyPrefix: PColumnKey = [] +): boolean { + if (acc === undefined) return false; + switch (acc.resourceType.name) { + case ResourceMapResourceTypeName: { + let isComplete = acc.getInputsLocked(); + for (const keyStr of acc.listInputFields()) { + const value = acc.resolve({ field: keyStr, assertFieldType: 'Input' }); + if (value === undefined) isComplete = false; + else { + const key = [...keyPrefix, ...JSON.parse(keyStr)] as PColumnKey; + const converted = resourceParser(value); + if (converted === undefined) isComplete = false; + else data.push({ key, value: converted }); + } + } + return isComplete; + } + case ResourceMapResourcePartitionedTypeName: { + let isComplete = acc.getInputsLocked(); + for (const keyStr of acc.listInputFields()) { + const value = acc.resolve({ field: keyStr, assertFieldType: 'Input' }); + if (value === undefined) isComplete = false; + else { + const key = [...keyPrefix, ...JSON.parse(keyStr)] as PColumnKey; + isComplete = isComplete && populateResourceMapData(value, resourceParser, data, key); + } + } + return isComplete; + } + default: + throw new Error(`Unknown resource type: ${acc.resourceType.name}`); + } +} + +export function parseResourceMap( + acc: TreeNodeAccessor | undefined, + resourceParser: (acc: TreeNodeAccessor) => T | undefined +): PColumnResourceMapData> { + const data: PColumnResourceMapEntry>[] = []; + const isComplete = populateResourceMapData(acc, resourceParser, data, []); + return { isComplete, data }; +} diff --git a/model/src/index.ts b/model/src/index.ts index ff976f4..537597e 100644 --- a/model/src/index.ts +++ b/model/src/index.ts @@ -6,26 +6,40 @@ import { type InferOutputsType } from '@milaboratory/sdk-ui'; import { BlockArgs, BlockArgsValid } from './args'; +import { parseResourceMap } from './helpers'; export const platforma = BlockModel.create('Heavy') .initialArgs({}) .output('presets', (ctx) => - ctx.precalc?.resolve({ field: 'presets', assertFieldType: 'Input' })?.getFileHandle() + ctx.prerun?.resolve({ field: 'presets', assertFieldType: 'Input' })?.getFileHandle() ) .output('preset', (ctx) => - ctx.precalc?.resolve({ field: 'preset', assertFieldType: 'Input' })?.getDataAsString() + ctx.prerun?.resolve({ field: 'preset', assertFieldType: 'Input' })?.getDataAsString() ) .output('qc', (ctx) => - ctx.outputs?.resolve({ field: 'qc', assertFieldType: 'Input' })?.getDataAsJson() + parseResourceMap(ctx.outputs?.resolve({ field: 'qc', assertFieldType: 'Input' }), (acc) => + acc.getRemoteFileHandle() + ) + ) + + .output('reports', (ctx) => + parseResourceMap(ctx.outputs?.resolve({ field: 'reports', assertFieldType: 'Input' }), (acc) => + acc.getRemoteFileHandle() + ) + ) + + .output('clones', (ctx) => + parseResourceMap(ctx.outputs?.resolve({ field: 'clones', assertFieldType: 'Input' }), (acc) => + acc.listInputFields() + ) ) .output('inputOptions', (ctx) => { - const spectFromPool = ctx.resultPool - .getSpecsFromResultPool(); + const spectFromPool = ctx.resultPool.getSpecsFromResultPool(); return ctx.resultPool .getSpecsFromResultPool() .entries.filter((v) => { @@ -33,7 +47,7 @@ export const platforma = BlockModel.create('Heavy') const domain = v.obj.domain; return ( v.obj.name === 'pl7.app/sequencing/data' && - ((v.obj.valueType as string) === 'blob' || (v.obj.valueType as string) === 'file') && + (v.obj.valueType as string) === 'File' && domain !== undefined && (domain['pl7.app/fileExtension'] === 'fastq' || domain['pl7.app/fileExtension'] === 'fastq.gz') diff --git a/package.json b/package.json index 7b1a95c..9f25312 100644 --- a/package.json +++ b/package.json @@ -54,11 +54,16 @@ "@milaboratory/tengo-sdk": "file:/Volumes/Data/Projects/MiLaboratory/blocks-beta/tengo-sdk/milaboratory-tengo-sdk-1.0.14.tgz", "@milaboratory/tengo-template-builder": "file:/Volumes/Data/Projects/MiLaboratory/blocks-beta/tengo-template-builder" } + }, + "pnpm2": { + "overrides": { + "@milaboratory/tengo-sdk": "file:/Volumes/Data/Projects/MiLaboratory/blocks-beta/tengo-sdk", + "@milaboratory/pl-middle-layer": "file:/Volumes/Data/Projects/MiLaboratory/platforma/ts-pl-middle-layer", + "@milaboratory/sdk-ui": "file:/Volumes/Data/Projects/MiLaboratory/platforma/ts-sdk-ui" + } } }, "pnpm": { - "overrides": { - "@milaboratory/tengo-sdk": "file:/Volumes/Data/Projects/MiLaboratory/blocks-beta/tengo-sdk" - } + "overrides": {} } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e1e1e1..6318b46 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,32 +25,35 @@ catalogs: specifier: ^1.5.2 version: 1.5.2 '@milaboratory/milaboratories.samples-and-data': - specifier: 1.1.3 - version: 1.1.3 + specifier: 1.1.5 + version: 1.1.5 '@milaboratory/milaboratories.samples-and-data.model': - specifier: 1.1.0 - version: 1.1.0 + specifier: 1.1.1 + version: 1.1.1 '@milaboratory/pl-block-tools': specifier: ^2.1.5 version: 2.1.5 '@milaboratory/platforma-uikit': - specifier: ^1.0.25 - version: 1.0.25 + specifier: ^1.0.30 + version: 1.0.30 '@milaboratory/sdk-test': - specifier: ^1.4.13 - version: 1.4.13 + specifier: ^1.5.1 + version: 1.5.1 '@milaboratory/sdk-ui': - specifier: ^0.12.18 - version: 0.12.18 + specifier: ^0.12.21 + version: 0.12.21 '@milaboratory/sdk-vue': - specifier: ^1.0.33 - version: 1.0.33 + specifier: ^1.0.40 + version: 1.0.40 + '@milaboratory/tengo-sdk': + specifier: ^1.1.6 + version: 1.1.6 '@milaboratory/tengo-template-builder': - specifier: ^1.11.1 - version: 1.11.1 + specifier: ^1.13.0 + version: 1.13.0 '@vitejs/plugin-vue': - specifier: ^5.1.2 - version: 5.1.2 + specifier: ^5.1.3 + version: 5.1.3 tsup: specifier: ~8.1.2 version: 8.1.2 @@ -70,15 +73,12 @@ catalogs: specifier: ^3.4.38 version: 3.4.38 vue-tsc: - specifier: ^2.0.29 - version: 2.0.29 + specifier: ^2.1.2 + version: 2.1.2 zod: specifier: ^3.23.8 version: 3.23.8 -overrides: - '@milaboratory/tengo-sdk': file:/Volumes/Data/Projects/MiLaboratory/blocks-beta/tengo-sdk - importers: .: @@ -94,7 +94,7 @@ importers: version: link:workflow '@milaboratory/sdk-ui': specifier: 'catalog:' - version: 0.12.18 + version: 0.12.21 devDependencies: '@changesets/cli': specifier: 'catalog:' @@ -107,7 +107,7 @@ importers: dependencies: '@milaboratory/sdk-ui': specifier: 'catalog:' - version: 0.12.18 + version: 0.12.21 zod: specifier: 'catalog:' version: 3.23.8 @@ -129,17 +129,17 @@ importers: dependencies: '@milaboratory/milaboratories.samples-and-data': specifier: 'catalog:' - version: 1.1.3(typescript@5.5.4) + version: 1.1.5(typescript@5.5.4) '@milaboratory/milaboratories.samples-and-data.model': specifier: 'catalog:' - version: 1.1.0 + version: 1.1.1 this-block: specifier: workspace:@milaboratory/milaboratories.mixcr-clonotyping@* version: link:.. devDependencies: '@milaboratory/sdk-test': specifier: 'catalog:' - version: 1.4.13(@milaboratory/sdk-model@1.3.9)(@types/node@22.0.0) + version: 1.5.1(@milaboratory/sdk-model@1.3.9)(@types/node@22.0.0) typescript: specifier: 'catalog:' version: 5.5.4 @@ -169,13 +169,13 @@ importers: version: link:../model '@milaboratory/platforma-uikit': specifier: 'catalog:' - version: 1.0.25(typescript@5.5.4) + version: 1.0.30(typescript@5.5.4) '@milaboratory/sdk-ui': specifier: 'catalog:' - version: 0.12.18 + version: 0.12.21 '@milaboratory/sdk-vue': specifier: 'catalog:' - version: 1.0.33(@milaboratory/helpers@1.5.2)(@milaboratory/platforma-uikit@1.0.25(typescript@5.5.4))(@milaboratory/sdk-ui@0.12.18)(vue@3.4.38(typescript@5.5.4)) + version: 1.0.40(@milaboratory/helpers@1.5.2)(@milaboratory/sdk-ui@0.12.21)(typescript@5.5.4)(vue@3.4.38(typescript@5.5.4)) utility-types: specifier: 'catalog:' version: 3.11.0 @@ -188,7 +188,7 @@ importers: devDependencies: '@vitejs/plugin-vue': specifier: 'catalog:' - version: 5.1.2(vite@5.4.2(@types/node@22.0.0))(vue@3.4.38(typescript@5.5.4)) + version: 5.1.3(vite@5.4.2(@types/node@22.0.0))(vue@3.4.38(typescript@5.5.4)) typescript: specifier: 'catalog:' version: 5.5.4 @@ -197,16 +197,16 @@ importers: version: 5.4.2(@types/node@22.0.0) vue-tsc: specifier: 'catalog:' - version: 2.0.29(typescript@5.5.4) + version: 2.1.2(typescript@5.5.4) workflow: devDependencies: '@milaboratory/tengo-sdk': - specifier: file:/Volumes/Data/Projects/MiLaboratory/blocks-beta/tengo-sdk - version: file:../tengo-sdk + specifier: 'catalog:' + version: 1.1.6 '@milaboratory/tengo-template-builder': specifier: 'catalog:' - version: 1.11.1 + version: 1.13.0 packages: @@ -823,20 +823,20 @@ packages: '@milaboratory/helpers@1.5.2': resolution: {integrity: sha512-9UUACVZsUHeI4IJiRXNBgzq/3yFRXChJmr4dU8fco92jMd5tp2UziIwh/OzVrmbSMlm7dWWHXJ6dg3EYmD+qdg==, tarball: https://npm.pkg.github.com/download/@milaboratory/helpers/1.5.2/470283b6fc0544519e4c687e9b1aea6fe464300a} - '@milaboratory/milaboratories.samples-and-data.model@1.1.0': - resolution: {integrity: sha512-4uk4cQBdjnyDOOBoASrFXsULsfy+O4JwjUtLGMXEr6m3x0IkU/RSMd5z7RO0zJ9FDBG5ClMctmTr3GGoLnsnig==, tarball: https://npm.pkg.github.com/download/@milaboratory/milaboratories.samples-and-data.model/1.1.0/fcafc9b46283adf5f816e934ced115c4d0af1378} + '@milaboratory/milaboratories.samples-and-data.model@1.1.1': + resolution: {integrity: sha512-ZsJpyirY9RRz1MPX7DTfWGywEdzACjass+uAm6B7TWEWeM6kb/MYRTfgElsK6OQ0WR0qJwXxrbdrrtXE8caWGg==, tarball: https://npm.pkg.github.com/download/@milaboratory/milaboratories.samples-and-data.model/1.1.1/cd217e943a323d6cdd3a6143113d5bb1a89b69ec} - '@milaboratory/milaboratories.samples-and-data.ui@1.3.0': - resolution: {integrity: sha512-2JL6NA9GucCX7MykeKuihQfcYlC3zNvpw+/CTpqpYjnG9EOuceIg7og/dqSMSq4abjJNUn9U9UBE7eCEpTMGeA==, tarball: https://npm.pkg.github.com/download/@milaboratory/milaboratories.samples-and-data.ui/1.3.0/fb37c210a13726cc7a8a3908281d949b83efd983} + '@milaboratory/milaboratories.samples-and-data.ui@1.3.2': + resolution: {integrity: sha512-AOONpHstjYl4ymvdbf1+jqabTzNckGnamD3MKnwLycB/kpCi82znTs1u9nqY1MaCVImErXQWwAldpoc4jmoD4w==, tarball: https://npm.pkg.github.com/download/@milaboratory/milaboratories.samples-and-data.ui/1.3.2/0b2a22f870957993777a126b1473656dc695e653} - '@milaboratory/milaboratories.samples-and-data.workflow@1.4.0': - resolution: {integrity: sha512-ykSvOUdF2c2wu8ysEQRb616gBf4IvaNyEopEwBQYLZt8L9ljN5oBiSLAJ6VdZwbh9t67RatlXigKN4ZcWMWYiQ==, tarball: https://npm.pkg.github.com/download/@milaboratory/milaboratories.samples-and-data.workflow/1.4.0/6df26df085db27c8df52dd1a124f58494af4fe56} + '@milaboratory/milaboratories.samples-and-data.workflow@1.4.2': + resolution: {integrity: sha512-n3CVeQ9+jZF/7ssnN08QQaiax9JSpgiu/eiSaCquSq3/cEMuEOm8M3f+Y3oqEQPTg1V83O6Hp1PaOU0l6+ojog==, tarball: https://npm.pkg.github.com/download/@milaboratory/milaboratories.samples-and-data.workflow/1.4.2/b13e778e398b51a7ad0f8b20b61e19ef53c1772a} - '@milaboratory/milaboratories.samples-and-data@1.1.3': - resolution: {integrity: sha512-hPI/k4BYDr8+h9VZIBXXrhAyl1kBNt6SHC8RQ1m+weARqwG7swS3rLFozQJ4zrYpbpxAkG2s1rJq3d7lLtpX+w==, tarball: https://npm.pkg.github.com/download/@milaboratory/milaboratories.samples-and-data/1.1.3/8d3b5a01eff4e8150cd5369e36b7406d74b76b9c} + '@milaboratory/milaboratories.samples-and-data@1.1.5': + resolution: {integrity: sha512-6cq3U1TNCDA/ShotQgPlhSxH3nOTDmRf29upr5Lo861zwKvk0aUG1JA20GxaFsgNS2Lvr19kiO+RZ9ACzvifFQ==, tarball: https://npm.pkg.github.com/download/@milaboratory/milaboratories.samples-and-data/1.1.5/ad5a3154f826d9dd30f1ceb4f23ae9190413c02a} - '@milaboratory/pframes-node@0.4.15': - resolution: {integrity: sha512-FJOuc7AylExZxKZmaALFPR641q/+ZznVV5zwTU6Nczq9/LIugFCgfm2Y8Cp+PuDFQ/V8jCytM3hYo8fTGkYyaw==, tarball: https://npm.pkg.github.com/download/@milaboratory/pframes-node/0.4.15/0575620a3d9689e957862f1513a7493264c0bc68} + '@milaboratory/pframes-node@0.4.21': + resolution: {integrity: sha512-JEh73e2m2e5ZRGIN6zu/YcRmjmqarrlQU2oHHBR11UHWbyIR2Cf+hRq3rz2mYKEIkB7KF5QJYrL0cqXcm3Gnnw==, tarball: https://npm.pkg.github.com/download/@milaboratory/pframes-node/0.4.21/8c0c5aaee88751cbf4b8faff86a9c2b09402b611} peerDependencies: '@milaboratory/sdk-model': '*' @@ -844,8 +844,8 @@ packages: resolution: {integrity: sha512-8F28MkHQO0u9YHsmTmocWd6tQH9yyCBpoGNQh3vCHkxsQXKoj9H1zjyxyK4b/eHRFKxH4lcTRk7EgzfUFRqwKQ==, tarball: https://npm.pkg.github.com/download/@milaboratory/pl-block-tools/2.1.5/a0c97d8f6dbd01d724330e8ccd1c80d2e00cc39a} hasBin: true - '@milaboratory/pl-client-v2@2.4.9': - resolution: {integrity: sha512-TO8X7cyGs5R4ZUS1ahRpAC59/tUKPWqdfrDg8E/JH/VWwnbVowiXIJehlgbliMWa/X87XxXFsW5Q5MVkXrM1Ew==, tarball: https://npm.pkg.github.com/download/@milaboratory/pl-client-v2/2.4.9/7c7135ad01e692f10a2e66b44bda234daf12c31a} + '@milaboratory/pl-client-v2@2.4.10': + resolution: {integrity: sha512-O2HN+mXPOlrk+kH541QAxE+rcrbVVDiqko+usPq1AC/mxM2L5pbpjnIrgJqCKgxU6OnQaYXHsoNRFOK/earDvg==, tarball: https://npm.pkg.github.com/download/@milaboratory/pl-client-v2/2.4.10/49bb4a3bfb4b78785e4109e08c121a3132f28013} '@milaboratory/pl-drivers@1.2.10': resolution: {integrity: sha512-LDGrsmWEuBBLZ6rDwQjx2iGW3P1rYGkp4oXv2kjfGJqJ6Of+Zw8FUWtgGh7cTaGPEKcYk4OWjEXLdUdPXnmr1Q==, tarball: https://npm.pkg.github.com/download/@milaboratory/pl-drivers/1.2.10/206df6696c78d6ad3ba4bd2ba3fd90e74cca4f46} @@ -856,8 +856,8 @@ packages: '@milaboratory/pl-middle-layer-model@1.2.16': resolution: {integrity: sha512-WT5TKDSOQ/iLUDFF3QW1En/YnbR/J5TZlHY0endrYpxVR40qfLpoOkCrHJki0EXG0j9AWcyTyFSrpxYX7OIkeQ==, tarball: https://npm.pkg.github.com/download/@milaboratory/pl-middle-layer-model/1.2.16/900734158fde8d99b72533ed6b82c3a9b66f4b8c} - '@milaboratory/pl-middle-layer@1.9.30': - resolution: {integrity: sha512-jqG3kpyK7msjnAo7C4+HPD7aaxHj9k+Jqee73+098mg33eeLy30ULM3y+JLSB1GNVSwnQLp2anmRW4g6FK/OZQ==, tarball: https://npm.pkg.github.com/download/@milaboratory/pl-middle-layer/1.9.30/c351308f4cc1136c1d0d2b0720d3d5ff1c675d02} + '@milaboratory/pl-middle-layer@1.10.1': + resolution: {integrity: sha512-DavPhgGOAbCpVKPMtTo2ZCUxHEplsYoDnIAqfmVmYu9J/ifrmmy651EAhFOPTjQDMqQrpYoBiN5V7ZVzhgdptQ==, tarball: https://npm.pkg.github.com/download/@milaboratory/pl-middle-layer/1.10.1/5dc179cef63533c05f7466e574a5eb08766ef30b} hasBin: true '@milaboratory/pl-tree@1.3.5': @@ -866,45 +866,38 @@ packages: '@milaboratory/platforma-core@0.1.5': resolution: {integrity: sha512-h9BW6SnX7zcNMrc3fl70DJuVUPTm+pn6/buKMZJypp/bV51DwT50FiAhCBklCkttwtngZqKXE0i//1H00V0qNg==, tarball: https://npm.pkg.github.com/download/@milaboratory/platforma-core/0.1.5/cc46c20f983d2c291aec707200e5ff46e082c1a6} - '@milaboratory/platforma-uikit@1.0.24': - resolution: {integrity: sha512-m7/Hsc9shWGX8LDFieQTdSnoOaz0sUkiKKtQBulyqH+AItA8f3AWI73h5if4qwa9gBntiUaaynIIfptCdpzm3g==, tarball: https://npm.pkg.github.com/download/@milaboratory/platforma-uikit/1.0.24/d752a549563176927e95a406143e7513b4548671} + '@milaboratory/platforma-uikit@1.0.29': + resolution: {integrity: sha512-/804A08lL58MhoeqK3EdBS020BOKdANPsFvYQLvgSNvDu1L/4ooNyiMAuiCnuoxiOU4TQYJ8GCfvGIV0JAo5vg==, tarball: https://npm.pkg.github.com/download/@milaboratory/platforma-uikit/1.0.29/051a588e6e40fa089d0ce6425bee2efd59f17cac} engines: {node: ^20.12.2, npm: ^10.5.2} - '@milaboratory/platforma-uikit@1.0.25': - resolution: {integrity: sha512-FM0WNvEZqPCOcZpkkKWK0WlryOMEUB/jSx8knOezzqtEDVcakFMI7kfkHOQ3u8xxkeOZ3knPJRFhnPrtv0AcMA==, tarball: https://npm.pkg.github.com/download/@milaboratory/platforma-uikit/1.0.25/24b359aca80c4e8aa6b27b89eeee730ce56509b4} + '@milaboratory/platforma-uikit@1.0.30': + resolution: {integrity: sha512-jLbsKiE8IYeaylv0Umj5F7stXZ70kG4OJined2/2dm97j9lqAumfq1iELxrECXgc3vsDSLZAnLmGQFBQeJmszA==, tarball: https://npm.pkg.github.com/download/@milaboratory/platforma-uikit/1.0.30/f0c7138c913cc19894893002d37ce85d9ca86220} engines: {node: ^20.12.2, npm: ^10.5.2} '@milaboratory/sdk-model@1.3.7': resolution: {integrity: sha512-cWrAfQHw5h7W57BpURHv5v5ni5nO1EWIYiE52pbnh5i3CT87ZLvrNLRFJTeY1tcqOnSDrkk0Mcln1Hdylo3h0Q==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-model/1.3.7/2cae8c7bcc431adebc4337bd2402359666b55ff1} - '@milaboratory/sdk-model@1.3.8': - resolution: {integrity: sha512-7+4Hvmsu3sqWMBCyxzCs/ShdhINKIK0yUf0Qe2Br5Fw9vfKOLBz/qED9ohSUrbm3VzJYgWgtWaVl2ipBC0IjcA==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-model/1.3.8/ad3538e61e7a109f553b0821d08ae0bffe4f302d} - '@milaboratory/sdk-model@1.3.9': resolution: {integrity: sha512-ZuJYcbNpbpNEjqBrpp7iY+QpwSIeQcfgP+28MiSctb0PrhHgascC2QvetetFczo6tKJlT2ZvmZ5spdgz0lvgYg==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-model/1.3.9/4e3091eb6014b20b67d7609a54c6014a3ad261ea} - '@milaboratory/sdk-test@1.4.13': - resolution: {integrity: sha512-TJmj4c5MF2+5B7XKC9492Uxhwdu8BO3UhmUcBAj7YOeoUngWIyj9EBz7E+9HlCoE41v1kvhJd8v5PLZ4NTxygg==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-test/1.4.13/1538cc9b06e931e40b637ceebadd7c686ebbf464} - - '@milaboratory/sdk-ui@0.12.15': - resolution: {integrity: sha512-zNH8dpq9B1mOsk60pq3paSEuDI7vUMzCdV9EPn7aPlA/YZ8BH16+pOdW5KYC+3SDCz+xiOzhLzQ4h3P8Tv6H1w==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-ui/0.12.15/1195aa1a3cc84d1dc4a934a2cd8c807523941e0b} + '@milaboratory/sdk-test@1.5.1': + resolution: {integrity: sha512-brsi01p2qYte7wXmEHIDbou7acN+YX8enEqq6T6JEJQLL7iA7vi5ch33hPnfKtQs3PlPk0wRYXLfBe9Knn3+BQ==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-test/1.5.1/0f9c5e98b75423472b0e3aae7b6fb7e031d4f84c} - '@milaboratory/sdk-ui@0.12.18': - resolution: {integrity: sha512-351SLm7CD3q0KRVxgIkhnVlznuxBC5/K7GpMyx3ApNJJNZmGcZ2n6IZFZNoJK5kb7bsd3d8VcOoGDz9zvEGeFg==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-ui/0.12.18/c422a087ce100ad14ee180164aaff560f5ee8c12} + '@milaboratory/sdk-ui@0.12.21': + resolution: {integrity: sha512-wQnaHRIUcV3IWnMDUiRVRBPIFDzoyZvIQLBMD6hYZdMK0uj4+Q1rPyq+E+8ZEgNv84uvI8F18pEpNt6EXpZihA==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-ui/0.12.21/e3a89013847aa6039ddee63d8d0656f8acf601ae} - '@milaboratory/sdk-vue@1.0.33': - resolution: {integrity: sha512-uR12SH1kheVz1s8K7gvRcE2FBO+ukRE4N67XEkThAjnHvkw1EmcPmgnU3aRSW/h6uHsq1C5QHXnr77rHe/tTOg==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-vue/1.0.33/36106e29855131fa72f4c26c4a40c6e7714bf581} + '@milaboratory/sdk-vue@1.0.40': + resolution: {integrity: sha512-oyqhg1fQ+9zWuBYUJQ8Z/wUYA4koYd2uWuyfQW0tgR39EKQLbZLkx+D26g6qCWsVixj9UYdZGhkvtE9ocWw0mw==, tarball: https://npm.pkg.github.com/download/@milaboratory/sdk-vue/1.0.40/7bdb307473d7dc7a311b7d1f091b16500173e822} peerDependencies: '@milaboratory/helpers': ^1.5.1 - '@milaboratory/platforma-uikit': ^1.0.13 '@milaboratory/sdk-ui': ^0.12.10 vue: ^3.4.31 - '@milaboratory/tengo-sdk@file:../tengo-sdk': - resolution: {directory: ../tengo-sdk, type: directory} + '@milaboratory/tengo-sdk@1.1.6': + resolution: {integrity: sha512-v0EctZc0N3f2IT/bI2Lwv4eKPi6isvWZQB5peyQYRUMg82nlH5RMDrafqAyiW2Df5w97K8JMwqr6h001oYBmyw==, tarball: https://npm.pkg.github.com/download/@milaboratory/tengo-sdk/1.1.6/329020d26ef8960abd07e0b9e6f4cd1748635788} - '@milaboratory/tengo-template-builder@1.11.1': - resolution: {integrity: sha512-Z6/C85vUUBO44Utsre2/TbRbNwaMsOa9l4AXUryb9vtvh4gcnHbr2wwLzv1iZ7mBeHVyk7iLk7vTLtbmooovvw==, tarball: https://npm.pkg.github.com/download/@milaboratory/tengo-template-builder/1.11.1/fec79d77cc7882eb05037c308252d3595a36d1c1} + '@milaboratory/tengo-template-builder@1.13.0': + resolution: {integrity: sha512-xokNWyp+IWC8JLIq6yUbLW1HA+qzLs+nEELv2LtHlUoKVH1JR5ju7fj5H4OeOgP9NIvKfjyzq4VpGjNSNa92Gw==, tarball: https://npm.pkg.github.com/download/@milaboratory/tengo-template-builder/1.13.0/e866030cc9ec80cee031541aa27bfd05f10d5221} hasBin: true '@milaboratory/tengo-tester@1.4.1': @@ -1380,8 +1373,8 @@ packages: '@types/triple-beam@1.3.5': resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} - '@vitejs/plugin-vue@5.1.2': - resolution: {integrity: sha512-nY9IwH12qeiJqumTCLJLE7IiNx7HZ39cbHaysEUd+Myvbz9KAqd2yq+U01Kab1R/H1BmiyM2ShTYlNH32Fzo3A==} + '@vitejs/plugin-vue@5.1.3': + resolution: {integrity: sha512-3xbWsKEKXYlmX82aOHufFQVnkbMC/v8fLpWwh6hWOUrK5fbbtBh9Q/WWse27BFgSy2/e2c0fz5Scgya9h2GLhw==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: vite: ^5.0.0 @@ -1405,24 +1398,18 @@ packages: '@vitest/utils@2.0.5': resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} - '@volar/language-core@2.4.0-alpha.18': - resolution: {integrity: sha512-JAYeJvYQQROmVRtSBIczaPjP3DX4QW1fOqW1Ebs0d3Y3EwSNRglz03dSv0Dm61dzd0Yx3WgTW3hndDnTQqgmyg==} + '@volar/language-core@2.4.1': + resolution: {integrity: sha512-9AKhC7Qn2mQYxj7Dz3bVxeOk7gGJladhWixUYKef/o0o7Bm4an+A3XvmcTHVqZ8stE6lBVH++g050tBtJ4TZPQ==} - '@volar/source-map@2.4.0-alpha.18': - resolution: {integrity: sha512-MTeCV9MUwwsH0sNFiZwKtFrrVZUK6p8ioZs3xFzHc2cvDXHWlYN3bChdQtwKX+FY2HG6H3CfAu1pKijolzIQ8g==} + '@volar/source-map@2.4.1': + resolution: {integrity: sha512-Xq6ep3OZg9xUqN90jEgB9ztX5SsTz1yiV8wiQbcYNjWkek+Ie3dc8l7AVt3EhDm9mSIR58oWczHkzM2H6HIsmQ==} - '@volar/typescript@2.4.0-alpha.18': - resolution: {integrity: sha512-sXh5Y8sqGUkgxpMWUGvRXggxYHAVxg0Pa1C42lQZuPDrW6vHJPR0VCK8Sr7WJsAW530HuNQT/ZIskmXtxjybMQ==} - - '@vue/compiler-core@3.4.34': - resolution: {integrity: sha512-Z0izUf32+wAnQewjHu+pQf1yw00EGOmevl1kE+ljjjMe7oEfpQ+BI3/JNK7yMB4IrUsqLDmPecUrpj3mCP+yJQ==} + '@volar/typescript@2.4.1': + resolution: {integrity: sha512-UoRzC0PXcwajFQTu8XxKSYNsWNBtVja6Y9gC8eLv7kYm+UEKJCcZ8g7dialsOYA0HKs3Vpg57MeCsawFLC6m9Q==} '@vue/compiler-core@3.4.38': resolution: {integrity: sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==} - '@vue/compiler-dom@3.4.34': - resolution: {integrity: sha512-3PUOTS1h5cskdOJMExCu2TInXuM0j60DRPpSCJDqOCupCfUZCJoyQmKtRmA8EgDNZ5kcEE7vketamRZfrEuVDw==} - '@vue/compiler-dom@3.4.38': resolution: {integrity: sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==} @@ -1438,8 +1425,8 @@ packages: '@vue/devtools-api@6.6.3': resolution: {integrity: sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==} - '@vue/language-core@2.0.29': - resolution: {integrity: sha512-o2qz9JPjhdoVj8D2+9bDXbaI4q2uZTHQA/dbyZT4Bj1FR9viZxDJnLcKVHfxdn6wsOzRgpqIzJEEmSSvgMvDTQ==} + '@vue/language-core@2.1.2': + resolution: {integrity: sha512-tt2J7C+l0J/T5PaLhJ0jvCCi0JNwu3e8azWTYxW3jmAW5B/dac0g5UxmI7l59CQgCGFotqUqI3tXjfZgoWNtog==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -1460,9 +1447,6 @@ packages: peerDependencies: vue: 3.4.38 - '@vue/shared@3.4.34': - resolution: {integrity: sha512-x5LmiRLpRsd9KTjAB8MPKf0CDPMcuItjP0gbNqFCIgL1I8iYp4zglhj9w9FPCdIbHG2M91RVeIbArFfFTz9I3A==} - '@vue/shared@3.4.38': resolution: {integrity: sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==} @@ -2888,8 +2872,8 @@ packages: peerDependencies: vue: ^3.2.0 - vue-tsc@2.0.29: - resolution: {integrity: sha512-MHhsfyxO3mYShZCGYNziSbc63x7cQ5g9kvijV7dRe1TTXBRLxXyL0FnXWpUF1xII2mJ86mwYpYsUmMwkmerq7Q==} + vue-tsc@2.1.2: + resolution: {integrity: sha512-PH1BDxWT3eaPhl73elyZj6DV0nR3K4IFoUM1sGzMXXQneovVUwHQytdSyAHiED5MtEINGSHpL/Hs9ch+c/tDTw==} hasBin: true peerDependencies: typescript: '>=5.0.0' @@ -3936,40 +3920,40 @@ snapshots: '@milaboratory/helpers@1.5.2': {} - '@milaboratory/milaboratories.samples-and-data.model@1.1.0': + '@milaboratory/milaboratories.samples-and-data.model@1.1.1': dependencies: - '@milaboratory/sdk-ui': 0.12.15 + '@milaboratory/sdk-ui': 0.12.21 zod: 3.23.8 - '@milaboratory/milaboratories.samples-and-data.ui@1.3.0(typescript@5.5.4)': + '@milaboratory/milaboratories.samples-and-data.ui@1.3.2(typescript@5.5.4)': dependencies: '@ag-grid-community/client-side-row-model': 32.1.0 '@ag-grid-community/core': 32.1.0 '@ag-grid-community/styles': 32.1.0 '@ag-grid-community/vue3': 32.1.0(typescript@5.5.4) '@milaboratory/helpers': 1.5.2 - '@milaboratory/milaboratories.samples-and-data.model': 1.1.0 - '@milaboratory/platforma-uikit': 1.0.24(typescript@5.5.4) - '@milaboratory/sdk-ui': 0.12.18 - '@milaboratory/sdk-vue': 1.0.33(@milaboratory/helpers@1.5.2)(@milaboratory/platforma-uikit@1.0.24(typescript@5.5.4))(@milaboratory/sdk-ui@0.12.18)(vue@3.4.38(typescript@5.5.4)) + '@milaboratory/milaboratories.samples-and-data.model': 1.1.1 + '@milaboratory/platforma-uikit': 1.0.29(typescript@5.5.4) + '@milaboratory/sdk-ui': 0.12.21 + '@milaboratory/sdk-vue': 1.0.40(@milaboratory/helpers@1.5.2)(@milaboratory/sdk-ui@0.12.21)(typescript@5.5.4)(vue@3.4.38(typescript@5.5.4)) utility-types: 3.11.0 vue: 3.4.38(typescript@5.5.4) zod: 3.23.8 transitivePeerDependencies: - typescript - '@milaboratory/milaboratories.samples-and-data.workflow@1.4.0': {} + '@milaboratory/milaboratories.samples-and-data.workflow@1.4.2': {} - '@milaboratory/milaboratories.samples-and-data@1.1.3(typescript@5.5.4)': + '@milaboratory/milaboratories.samples-and-data@1.1.5(typescript@5.5.4)': dependencies: - '@milaboratory/milaboratories.samples-and-data.model': 1.1.0 - '@milaboratory/milaboratories.samples-and-data.ui': 1.3.0(typescript@5.5.4) - '@milaboratory/milaboratories.samples-and-data.workflow': 1.4.0 - '@milaboratory/sdk-ui': 0.12.18 + '@milaboratory/milaboratories.samples-and-data.model': 1.1.1 + '@milaboratory/milaboratories.samples-and-data.ui': 1.3.2(typescript@5.5.4) + '@milaboratory/milaboratories.samples-and-data.workflow': 1.4.2 + '@milaboratory/sdk-ui': 0.12.21 transitivePeerDependencies: - typescript - '@milaboratory/pframes-node@0.4.15(@milaboratory/sdk-model@1.3.9)': + '@milaboratory/pframes-node@0.4.21(@milaboratory/sdk-model@1.3.9)': dependencies: '@mapbox/node-pre-gyp': 1.0.11 '@milaboratory/pl-middle-layer-model': 1.2.16 @@ -3994,7 +3978,7 @@ snapshots: transitivePeerDependencies: - aws-crt - '@milaboratory/pl-client-v2@2.4.9': + '@milaboratory/pl-client-v2@2.4.10': dependencies: '@grpc/grpc-js': 1.11.1 '@milaboratory/ts-helpers': 1.0.19 @@ -4013,7 +3997,7 @@ snapshots: dependencies: '@grpc/grpc-js': 1.11.1 '@milaboratory/computable': 2.1.2 - '@milaboratory/pl-client-v2': 2.4.9 + '@milaboratory/pl-client-v2': 2.4.10 '@milaboratory/pl-tree': 1.3.5 '@milaboratory/sdk-model': 1.3.9 '@milaboratory/ts-helpers': 1.0.19 @@ -4038,16 +4022,17 @@ snapshots: utility-types: 3.11.0 zod: 3.23.8 - '@milaboratory/pl-middle-layer@1.9.30(@milaboratory/sdk-model@1.3.9)': + '@milaboratory/pl-middle-layer@1.10.1(@milaboratory/sdk-model@1.3.9)': dependencies: '@milaboratory/computable': 2.1.2 - '@milaboratory/pframes-node': 0.4.15(@milaboratory/sdk-model@1.3.9) + '@milaboratory/pframes-node': 0.4.21(@milaboratory/sdk-model@1.3.9) '@milaboratory/pl-block-tools': 2.1.5 - '@milaboratory/pl-client-v2': 2.4.9 + '@milaboratory/pl-client-v2': 2.4.10 '@milaboratory/pl-drivers': 1.2.10 '@milaboratory/pl-middle-layer-model': 1.2.16 '@milaboratory/pl-tree': 1.3.5 - '@milaboratory/sdk-ui': 0.12.18 + '@milaboratory/sdk-ui': 0.12.21 + '@milaboratory/tengo-sdk': 1.1.6 '@milaboratory/ts-helpers': 1.0.19 canonicalize: 2.0.0 denque: 2.1.0 @@ -4065,7 +4050,7 @@ snapshots: '@milaboratory/pl-tree@1.3.5': dependencies: '@milaboratory/computable': 2.1.2 - '@milaboratory/pl-client-v2': 2.4.9 + '@milaboratory/pl-client-v2': 2.4.10 '@milaboratory/ts-helpers': 1.0.19 denque: 2.1.0 utility-types: 3.11.0 @@ -4077,7 +4062,7 @@ snapshots: dependencies: zod: 3.23.8 - '@milaboratory/platforma-uikit@1.0.24(typescript@5.5.4)': + '@milaboratory/platforma-uikit@1.0.29(typescript@5.5.4)': dependencies: '@milaboratory/helpers': 1.5.2 '@milaboratory/platforma-core': 0.1.5 @@ -4089,7 +4074,7 @@ snapshots: transitivePeerDependencies: - typescript - '@milaboratory/platforma-uikit@1.0.25(typescript@5.5.4)': + '@milaboratory/platforma-uikit@1.0.30(typescript@5.5.4)': dependencies: '@milaboratory/helpers': 1.5.2 '@milaboratory/platforma-core': 0.1.5 @@ -4103,19 +4088,17 @@ snapshots: '@milaboratory/sdk-model@1.3.7': {} - '@milaboratory/sdk-model@1.3.8': {} - '@milaboratory/sdk-model@1.3.9': dependencies: zod: 3.23.8 - '@milaboratory/sdk-test@1.4.13(@milaboratory/sdk-model@1.3.9)(@types/node@22.0.0)': + '@milaboratory/sdk-test@1.5.1(@milaboratory/sdk-model@1.3.9)(@types/node@22.0.0)': dependencies: '@milaboratory/computable': 2.1.2 - '@milaboratory/pl-client-v2': 2.4.9 - '@milaboratory/pl-middle-layer': 1.9.30(@milaboratory/sdk-model@1.3.9) + '@milaboratory/pl-client-v2': 2.4.10 + '@milaboratory/pl-middle-layer': 1.10.1(@milaboratory/sdk-model@1.3.9) '@milaboratory/pl-tree': 1.3.5 - '@milaboratory/sdk-ui': 0.12.18 + '@milaboratory/sdk-ui': 0.12.21 '@milaboratory/ts-helpers': 1.0.19 vitest: 2.0.5(@types/node@22.0.0) transitivePeerDependencies: @@ -4137,38 +4120,26 @@ snapshots: - supports-color - terser - '@milaboratory/sdk-ui@0.12.15': - dependencies: - '@milaboratory/sdk-model': 1.3.8 - utility-types: 3.11.0 - - '@milaboratory/sdk-ui@0.12.18': + '@milaboratory/sdk-ui@0.12.21': dependencies: '@milaboratory/sdk-model': 1.3.9 utility-types: 3.11.0 zod: 3.23.8 - '@milaboratory/sdk-vue@1.0.33(@milaboratory/helpers@1.5.2)(@milaboratory/platforma-uikit@1.0.24(typescript@5.5.4))(@milaboratory/sdk-ui@0.12.18)(vue@3.4.38(typescript@5.5.4))': - dependencies: - '@milaboratory/helpers': 1.5.2 - '@milaboratory/platforma-uikit': 1.0.24(typescript@5.5.4) - '@milaboratory/sdk-ui': 0.12.18 - vue: 3.4.38(typescript@5.5.4) - optionalDependencies: - '@rollup/rollup-linux-x64-gnu': 4.9.5 - - '@milaboratory/sdk-vue@1.0.33(@milaboratory/helpers@1.5.2)(@milaboratory/platforma-uikit@1.0.25(typescript@5.5.4))(@milaboratory/sdk-ui@0.12.18)(vue@3.4.38(typescript@5.5.4))': + '@milaboratory/sdk-vue@1.0.40(@milaboratory/helpers@1.5.2)(@milaboratory/sdk-ui@0.12.21)(typescript@5.5.4)(vue@3.4.38(typescript@5.5.4))': dependencies: '@milaboratory/helpers': 1.5.2 - '@milaboratory/platforma-uikit': 1.0.25(typescript@5.5.4) - '@milaboratory/sdk-ui': 0.12.18 + '@milaboratory/platforma-uikit': 1.0.30(typescript@5.5.4) + '@milaboratory/sdk-ui': 0.12.21 vue: 3.4.38(typescript@5.5.4) optionalDependencies: '@rollup/rollup-linux-x64-gnu': 4.9.5 + transitivePeerDependencies: + - typescript - '@milaboratory/tengo-sdk@file:../tengo-sdk': {} + '@milaboratory/tengo-sdk@1.1.6': {} - '@milaboratory/tengo-template-builder@1.11.1': + '@milaboratory/tengo-template-builder@1.13.0': dependencies: '@milaboratory/tengo-tester': 1.4.1 '@oclif/core': 3.27.0 @@ -4746,7 +4717,7 @@ snapshots: '@types/triple-beam@1.3.5': {} - '@vitejs/plugin-vue@5.1.2(vite@5.4.2(@types/node@22.0.0))(vue@3.4.38(typescript@5.5.4))': + '@vitejs/plugin-vue@5.1.3(vite@5.4.2(@types/node@22.0.0))(vue@3.4.38(typescript@5.5.4))': dependencies: vite: 5.4.2(@types/node@22.0.0) vue: 3.4.38(typescript@5.5.4) @@ -4784,26 +4755,18 @@ snapshots: loupe: 3.1.1 tinyrainbow: 1.2.0 - '@volar/language-core@2.4.0-alpha.18': + '@volar/language-core@2.4.1': dependencies: - '@volar/source-map': 2.4.0-alpha.18 + '@volar/source-map': 2.4.1 - '@volar/source-map@2.4.0-alpha.18': {} + '@volar/source-map@2.4.1': {} - '@volar/typescript@2.4.0-alpha.18': + '@volar/typescript@2.4.1': dependencies: - '@volar/language-core': 2.4.0-alpha.18 + '@volar/language-core': 2.4.1 path-browserify: 1.0.1 vscode-uri: 3.0.8 - '@vue/compiler-core@3.4.34': - dependencies: - '@babel/parser': 7.25.0 - '@vue/shared': 3.4.34 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.0 - '@vue/compiler-core@3.4.38': dependencies: '@babel/parser': 7.25.0 @@ -4812,11 +4775,6 @@ snapshots: estree-walker: 2.0.2 source-map-js: 1.2.0 - '@vue/compiler-dom@3.4.34': - dependencies: - '@vue/compiler-core': 3.4.34 - '@vue/shared': 3.4.34 - '@vue/compiler-dom@3.4.38': dependencies: '@vue/compiler-core': 3.4.38 @@ -4846,12 +4804,12 @@ snapshots: '@vue/devtools-api@6.6.3': {} - '@vue/language-core@2.0.29(typescript@5.5.4)': + '@vue/language-core@2.1.2(typescript@5.5.4)': dependencies: - '@volar/language-core': 2.4.0-alpha.18 - '@vue/compiler-dom': 3.4.34 + '@volar/language-core': 2.4.1 + '@vue/compiler-dom': 3.4.38 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.4.34 + '@vue/shared': 3.4.38 computeds: 0.0.1 minimatch: 9.0.5 muggle-string: 0.4.1 @@ -4881,8 +4839,6 @@ snapshots: '@vue/shared': 3.4.38 vue: 3.4.38(typescript@5.5.4) - '@vue/shared@3.4.34': {} - '@vue/shared@3.4.38': {} abbrev@1.1.1: {} @@ -6246,10 +6202,10 @@ snapshots: '@vue/devtools-api': 6.6.3 vue: 3.4.38(typescript@5.5.4) - vue-tsc@2.0.29(typescript@5.5.4): + vue-tsc@2.1.2(typescript@5.5.4): dependencies: - '@volar/typescript': 2.4.0-alpha.18 - '@vue/language-core': 2.0.29(typescript@5.5.4) + '@volar/typescript': 2.4.1 + '@vue/language-core': 2.1.2(typescript@5.5.4) semver: 7.6.3 typescript: 5.5.4 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c6670a6..86e1c60 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,21 +6,21 @@ packages: - test catalog: - '@milaboratory/tengo-template-builder': ^1.11.1 + '@milaboratory/tengo-template-builder': ^1.13.0 '@milaboratory/pl-block-tools': ^2.1.5 '@milaboratory/block-builder': ^1.2.3 - '@milaboratory/sdk-ui': ^0.12.18 - '@milaboratory/sdk-test': ^1.4.13 + '@milaboratory/sdk-ui': ^0.12.21 + '@milaboratory/sdk-test': ^1.5.1 - '@milaboratory/tengo-sdk': ^1.0.15 + '@milaboratory/tengo-sdk': ^1.1.6 - '@milaboratory/platforma-uikit': ^1.0.25 - '@milaboratory/sdk-vue': ^1.0.33 + '@milaboratory/platforma-uikit': ^1.0.30 + '@milaboratory/sdk-vue': ^1.0.40 '@milaboratory/helpers': ^1.5.2 'vue': ^3.4.38 - 'vue-tsc': ^2.0.29 + 'vue-tsc': ^2.1.2 'zod': ^3.23.8 'utility-types': ^3.11.0 @@ -30,7 +30,7 @@ catalog: 'vite': ^5.4.2 'vitest': ^2.0.5 - '@vitejs/plugin-vue': ^5.1.2 + '@vitejs/plugin-vue': ^5.1.3 '@ag-grid-community/core': ^32.1.0 '@ag-grid-community/client-side-row-model': ^32.1.0 @@ -40,5 +40,6 @@ catalog: '@changesets/cli': ^2.27.7 # other blocks used in tests - '@milaboratory/milaboratories.samples-and-data': 1.1.3 - '@milaboratory/milaboratories.samples-and-data.model': 1.1.0 + + '@milaboratory/milaboratories.samples-and-data': 1.1.5 + '@milaboratory/milaboratories.samples-and-data.model': 1.1.1 diff --git a/test/src/wf.test.ts b/test/src/wf.test.ts index a2c8a2a..c32bbef 100644 --- a/test/src/wf.test.ts +++ b/test/src/wf.test.ts @@ -13,10 +13,10 @@ import * as tp from 'node:timers/promises'; blockTest('empty imputs', { timeout: 10000 }, async ({ rawPrj: project, ml, helpers, expect }) => { const blockId = await project.addBlock('Block', myBlockSpec); - const stableState = await awaitStableState( + const stableState = (await awaitStableState( project.getBlockState(blockId), 5000 - ) as InferBlockState; + )) as InferBlockState; expect(stableState.outputs).toMatchObject({ inputOptions: { ok: true, value: [] } }); const presetsOutput = wrapOutputs(stableState.outputs).presets; const presetsStr = Buffer.from( @@ -34,10 +34,10 @@ blockTest( await project.setBlockArgs(blockId, { preset: 'milab-human-dna-xcr-7genes-multiplex' } satisfies BlockArgs); - const stableState = await awaitStableState( + const stableState = (await awaitStableState( project.getBlockState(blockId), 5000 - ) as InferBlockState; + )) as InferBlockState; expect(stableState.outputs).toMatchObject({ preset: { ok: true } }); } ); @@ -129,11 +129,32 @@ blockTest( preset: 'milab-human-dna-xcr-7genes-multiplex' } satisfies BlockArgs); await project.runBlock(clonotypingBlockId); - const clonotypingStableState2 = await helpers.awaitBlockDoneAndGetStableBlockState( + const clonotypingStableState2 = (await helpers.awaitBlockDoneAndGetStableBlockState( clonotypingBlockId, 10000 + )) as InferBlockState; + const outputs2 = wrapOutputs(clonotypingStableState2.outputs); + + console.dir(clonotypingStableState2, { depth: 8 }); + + expect(outputs2.reports.isComplete).toEqual(true); + + const alignJsonReportEntry = outputs2.reports.data.find( + (e) => e.key[1] === 'align' && e.key[2] === 'json' ); - - console.dir(clonotypingStableState2, { depth: 5 }); + + expect(alignJsonReportEntry).toBeDefined(); + + const alignJsonReport = JSON.parse( + Buffer.from( + await ml.driverKit.blobDriver.getContent(alignJsonReportEntry!.value!.handle) + ).toString('utf8') + ); + + expect(alignJsonReport.aligned).greaterThan(2); + + // console.dir(alignJsonReport, { depth: 5 }); + + console.dir(clonotypingStableState2, { depth: 8 }); } ); diff --git a/workflow/index.d.ts b/workflow/index.d.ts new file mode 100644 index 0000000..e8f569d --- /dev/null +++ b/workflow/index.d.ts @@ -0,0 +1,4 @@ +declare type TemplateFromFile = { readonly type: "from-file"; readonly path: string; }; +declare type TplName = "calculate-pfconv-params" | "export-clones" | "get-preset" | "list-presets" | "mixcr-analyze" | "prerun" | "process" | "main"; +declare const Templates: Record; +export { Templates }; diff --git a/workflow/index.js b/workflow/index.js new file mode 100644 index 0000000..d7dbb2f --- /dev/null +++ b/workflow/index.js @@ -0,0 +1,10 @@ +module.exports = { Templates: { + 'calculate-pfconv-params': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/calculate-pfconv-params.plj.gz') }, + 'export-clones': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/export-clones.plj.gz') }, + 'get-preset': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/get-preset.plj.gz') }, + 'list-presets': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/list-presets.plj.gz') }, + 'mixcr-analyze': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/mixcr-analyze.plj.gz') }, + 'prerun': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/prerun.plj.gz') }, + 'process': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/process.plj.gz') }, + 'main': { type: 'from-file', path: require.resolve('./dist/tengo/tpl/main.plj.gz') } +}} diff --git a/workflow/src/calculate-pfconv-params.tpl.tengo b/workflow/src/calculate-pfconv-params.tpl.tengo index 5bf9739..7678d5a 100644 --- a/workflow/src/calculate-pfconv-params.tpl.tengo +++ b/workflow/src/calculate-pfconv-params.tpl.tengo @@ -11,6 +11,28 @@ self.body(func(inputs) { preset := inputs.preset return { - params: pvconfParams + params: { + "axes": [{ + "column": "cloneId", + "spec": { + "name": "pl7.app/vdj/cloneId", + "type": "Long" + } + }], + "columns": [{ + "column": "readCount", + "id": "read-count", + "allowNA": false, + "spec": { + "name": "pl7.app/vdj/readCount", + "valueType": "Long", + "annotations": { + "pl7.app/label": "Number Of Reads" + } + } + }], + "storageFormat": "Binary", + "partitionKeyLength": 0 + } } }) diff --git a/workflow/src/export-clones.tpl.tengo b/workflow/src/export-clones.tpl.tengo new file mode 100644 index 0000000..46ae488 --- /dev/null +++ b/workflow/src/export-clones.tpl.tengo @@ -0,0 +1,42 @@ +// export clones + +self := import("@milaboratory/tengo-sdk:tpl") +smart := import("@milaboratory/tengo-sdk:smart") +ll := import("@milaboratory/tengo-sdk:ll") +xsv := import("@milaboratory/tengo-sdk:pframes.xsv") +pConstants := import("@milaboratory/tengo-sdk:pframes.constants") + +text := import("text") +json := import("json") + +self.defineOutputs("result") + +FILE_NAME_PREFIX := "result.clones_" +FILE_NAME_SUFFIX := ".tsv" +FILE_NAME_PREFIX_LEN := len(FILE_NAME_PREFIX) +FILE_NAME_SUFFIX_LEN := len(FILE_NAME_SUFFIX) + +self.body(func(inputs) { + pfconvParams := inputs.pfconvParams + data := self.rawInputs().data.getValue() + + csvMap := smart.structBuilder( + pConstants.RTYPE_P_COLUMN_DATA_RESOURCE_MAP, + json.encode({ keyLength: 1 }) + ) + + for fileName, file in data.inputs() { + if !text.has_prefix(fileName, FILE_NAME_PREFIX) || !text.has_suffix(fileName, FILE_NAME_SUFFIX) { + ll.panic("unedxpected file name: %v", fileName) + } + chain := fileName[FILE_NAME_PREFIX_LEN:(len(fileName) - FILE_NAME_SUFFIX_LEN)] + csvMap.createInputField(json.encode([chain])).set(file) + } + csvMap = csvMap.lockAndBuild() + + resultData := xsv.importFileMap(csvMap, "tsv", pfconvParams, { dataOnly: true }) + + return { + result: resultData + } +}) diff --git a/workflow/src/main.tpl.tengo b/workflow/src/main.tpl.tengo index 94c54a1..c6b6f4a 100644 --- a/workflow/src/main.tpl.tengo +++ b/workflow/src/main.tpl.tengo @@ -4,18 +4,20 @@ render := import("@milaboratory/tengo-sdk:render") maps := import("@milaboratory/tengo-sdk:maps") ll := import("@milaboratory/tengo-sdk:ll") +assets := import("@milaboratory/tengo-sdk:assets") smart := import("@milaboratory/tengo-sdk:smart") file := import("@milaboratory/tengo-sdk:file") llPFrames := import("@milaboratory/tengo-sdk:pframes.ll") +pframes := import("@milaboratory/tengo-sdk:pframes") exec := import("@milaboratory/tengo-sdk:exec") json := import("json") -getPresetTpl := ll.importTemplate(":get-preset") -calculatePfconvParamsTpl := ll.importTemplate(":calculate-pfconv-params") -processTpl := ll.importTemplate(":process") +getPresetTpl := assets.importTemplate(":get-preset") +calculatePfconvParamsTpl := assets.importTemplate(":calculate-pfconv-params") +processTpl := assets.importTemplate(":process") -wf.setPreRun(ll.importTemplate(":prerun")) +wf.setPreRun(assets.importTemplate(":prerun")) wf.body(func(args) { inputRef := args.input @@ -44,12 +46,25 @@ wf.body(func(args) { inputData: input.getFutureInputField("data") }) - exports := {} + exports := { + qc: { + spec: runMixcr.output("qc.spec"), + data: runMixcr.output("qc.data") + }, + reports: { + spec: runMixcr.output("reports.spec"), + data: runMixcr.output("reports.data") + } + } + + outputs := { + qc: pframes.exportColumnData(runMixcr.output("qc.data")), + reports: pframes.exportColumnData(runMixcr.output("reports.data")), + clones: pframes.exportFrame(runMixcr.output("clones")) + } return { - outputs: { - qc: runMixcr.output("qc") - }, + outputs: outputs, exports: exports } }) diff --git a/workflow/src/mixcr-analyze.tpl.tengo b/workflow/src/mixcr-analyze.tpl.tengo index 30738b6..21f2523 100644 --- a/workflow/src/mixcr-analyze.tpl.tengo +++ b/workflow/src/mixcr-analyze.tpl.tengo @@ -5,10 +5,14 @@ pConstants := import("@milaboratory/tengo-sdk:pframes.constants") ll := import("@milaboratory/tengo-sdk:ll") exec := import("@milaboratory/tengo-sdk:exec") smart := import("@milaboratory/tengo-sdk:smart") +assets := import("@milaboratory/tengo-sdk:assets") +render := import("@milaboratory/tengo-sdk:render") json := import("json") -self.defineOutputs("qc") +exportClonesTpl := assets.importTemplate(":export-clones") + +self.defineOutputs("qc", "reports", "clones") self.body(func(inputs) { inputData := inputs[pConstants.VALUE_FIELD_NAME] @@ -18,7 +22,7 @@ self.body(func(inputs) { fileExtension := params.fileExtension reports := params.reports - presetContent := inputs.presetContent.getDataAsJson() + presetContent := inputs.presetContent // already in JSON pfconvParams := inputs.pfconvParams // already in JSON if !is_map(presetContent) { @@ -58,21 +62,39 @@ self.body(func(inputs) { mixcrCmdBuilder.saveFile(report.fileTxt) } + mixcrCmdBuilder.saveFileSet("clones", "^result\\.clones_[A-Z0-9]+\\.tsv$") + mixcrCmd := mixcrCmdBuilder.run() reportsMap := smart.structBuilder( pConstants.RTYPE_P_COLUMN_DATA_RESOURCE_MAP, - json.encode({ keyLength: groupKeyLength }) + json.encode({ keyLength: 2 }) ) for report in reports { - reportsMap.createInputField(json.encode([report.id, "json"])).set(mixcrCmd.saveFile(report.fileJson)) - reportsMap.createInputField(json.encode([report.id, "txt"])).set(mixcrCmd.saveFile(report.fileTxt)) + reportsMap.createInputField(json.encode([report.id, "json"])).set(mixcrCmd.getFile(report.fileJson)) + reportsMap.createInputField(json.encode([report.id, "txt"])).set(mixcrCmd.getFile(report.fileTxt)) } - return { + // converting clone tables to p columns + clones := render.create(exportClonesTpl, { + data: mixcrCmd.getFileSet("clones"), + pfconvParams: pfconvParams + }).output("result", 24 * 60 * 60 * 1000) + + result := { qc: mixcrCmd.getFile("result.qc.json"), - reports: reportsMap.lockAndBuild() + reports: reportsMap.lockAndBuild(), + clones: clones } + + // cloneColumns := smart.mapBuilder() + + // for cloneColumn in pfconvParams.columns { + // cloneColumns.add(cloneColumn.id, ) + // result["clones/" + cloneColumn.id] = clones.getFutureInputField(cloneColumn.id) + // } + + return result } else { ll.panic("not yet supported") } diff --git a/workflow/src/prerun.tpl.tengo b/workflow/src/prerun.tpl.tengo index f5f09d6..3462b79 100644 --- a/workflow/src/prerun.tpl.tengo +++ b/workflow/src/prerun.tpl.tengo @@ -3,9 +3,10 @@ wf := import("@milaboratory/tengo-sdk:workflow") render := import("@milaboratory/tengo-sdk:render") ll := import("@milaboratory/tengo-sdk:ll") +assets := import("@milaboratory/tengo-sdk:assets") -listPresetsTpl := ll.importTemplate(":list-presets") -getPresetTpl := ll.importTemplate(":get-preset") +listPresetsTpl := assets.importTemplate(":list-presets") +getPresetTpl := assets.importTemplate(":get-preset") wf.body(func(args) { @@ -14,7 +15,7 @@ wf.body(func(args) { listPresets := render.create(listPresetsTpl, {}) outputs.presets = listPresets.output("presets", 24 * 60 * 60 * 1000) - if is_string(args.preset) { + if !is_undefined(args.preset) { getPreset := render.create(getPresetTpl, { preset: args.preset }) diff --git a/workflow/src/process.tpl.tengo b/workflow/src/process.tpl.tengo index e6dd1a0..4af8e2a 100644 --- a/workflow/src/process.tpl.tengo +++ b/workflow/src/process.tpl.tengo @@ -3,25 +3,34 @@ self := import("@milaboratory/tengo-sdk:tpl") ll := import("@milaboratory/tengo-sdk:ll") +assets := import("@milaboratory/tengo-sdk:assets") smart := import("@milaboratory/tengo-sdk:smart") file := import("@milaboratory/tengo-sdk:file") llPFrames := import("@milaboratory/tengo-sdk:pframes.ll") +pUtil := import("@milaboratory/tengo-sdk:pframes.util") +pConstants := import("@milaboratory/tengo-sdk:pframes.constants") json := import("json") -mixcrAnalyzeTpl := ll.importTemplate(":mixcr-analyze") +mixcrAnalyzeTpl := assets.importTemplate(":mixcr-analyze") self.awaitState("InputsLocked") self.awaitState("params", "ResourceReady") self.awaitState("inputSpec", "ResourceReady") +self.awaitState("presetContent", "ResourceReady") +self.awaitState("pfconvParams", "ResourceReady") self.body(func(inputs) { params := inputs.params preset := params.preset inputSpec := self.rawInputs().inputSpec.getValue().getDataAsJson() - presetContent := self.rawInputs().presetContent - pfconvParams := self.rawInputs().pfconvParams + presetContent := self.rawInputs().presetContent.getValue().getDataAsJson() + pfconvParams := self.rawInputs().pfconvParams.getValue().getDataAsJson() + + decomposition := pUtil.decomposePfconvCfg(pfconvParams) + purifiedPfconvCfg := decomposition.purifiedCfg + cloneColumnsSpec := decomposition.columnsSpec reports := [] @@ -29,7 +38,7 @@ self.body(func(inputs) { if step == "align" || step == "assemble" { reports = append(reports, { id: step, - fileJson: "result." + step + ".report.json" + fileJson: "result." + step + ".report.json", fileTxt: "result." + step + ".report.txt" }) } @@ -46,16 +55,30 @@ self.body(func(inputs) { fileExtension := inputSpec.domain["pl7.app/fileExtension"] + aggregationTargets := [{ + type: "Resource", + name: "qc" + }, { + type: "ResourceMap", + name: "reports", + keyLength: 2 // [reportType, reportFormat] + }] + + ll.assert(purifiedPfconvCfg.partitionKeyLength == 0, "unexpected pertition length") + ll.assert(purifiedPfconvCfg.storageFormat == "Binary", "unexpected format") + for columnCfg in purifiedPfconvCfg.columns { + aggCfg := { + type: "BinaryPartitioned", + name: "clones/" + columnCfg.id, + path: ["clones", columnCfg.id], + partitionKeyLength: 1 // [chain] + } + aggregationTargets = append(aggregationTargets, aggCfg) + } + mixcrResults := llPFrames.aggregate( self.rawInputs().inputData, [1], mixcrAnalyzeTpl, - [{ - type: "Resource", - name: "qc" - }, { - type: "ResourceMap", - name: "reports", - keyLength: 2 // [reportType, reportFormat] - }], + aggregationTargets, false, { params: smart.createJsonResource({ @@ -64,11 +87,54 @@ self.body(func(inputs) { reports: reports }), presetContent: presetContent, - pfconvParams: pfconvParams + pfconvParams: purifiedPfconvCfg } ) + clones := smart.structBuilder(pConstants.RTYPE_P_FRAME) + for columnId, columnSpec in cloneColumnsSpec { + clones.createInputField(columnId + ".spec").setJson(columnSpec) + clones.createInputField(columnId + ".data").set(mixcrResults.output("clones/" + columnId)) + } + return { - qc: mixcrResults.output("qc") + "qc.spec": { + kind: "PColumn", + name: "mixcr.com/qc", + valueType: "File", + axesSpec: [ + inputSpec.axesSpec[0] + ] + }, + "qc.data": mixcrResults.output("qc"), + + "reports.spec": { + kind: "PColumn", + name: "mixcr.com/report", + valueType: "File", + axesSpec: [ + inputSpec.axesSpec[0], + { + type: "String", + name: "mixcr.com/report/source", + annotations: { + "pl7.app/label": "Source MiXCR stage" + } + }, + { + type: "String", + name: "mixcr.com/report/format", + annotations: { + "pl7.app/label": "Report format" + }, + domain: { + "pl7.app/dense": json.encode(["json", "txt"]) + } + } + ] + }, + "reports.data": mixcrResults.output("reports"), + + "clones": clones.lockAndBuild() } })