diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4d936b6..e4df7b8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - node-version: [14.x, 16.x, 18.x, 20.7] + node-version: [14.x, 16.x, 18.x, 20.x] steps: - name: Checkout diff --git a/index.d.ts b/index.d.ts index a604911..4b1e02b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -639,7 +639,12 @@ declare class Request extends Mixin(Command, AsyncEventEmitter) { /** * Creates an instance of Request. */ - constructor(type: number, affectedOrRequestedClassUid: string, hasDataset: boolean); + constructor( + type: number, + affectedOrRequestedClassUid: string, + hasDataset: boolean, + metaSopClassUid?: string + ); /** * Gets affected SOP class UID. @@ -661,6 +666,16 @@ declare class Request extends Mixin(Command, AsyncEventEmitter) { */ setRequestedSopClassUid(requestedSopClassUid: string): void; + /** + * Gets meta SOP class UID. + */ + getMetaSopClassUid(): string | undefined; + + /** + * Sets meta SOP class UID. + */ + setMetaSopClassUid(metaSopClassUid: string): void; + /** * Gets affected SOP instance UID. */ @@ -1071,7 +1086,11 @@ declare class NCreateRequest extends Request { /** * Creates an instance of NCreateRequest. */ - constructor(affectedSopClassUid: string, affectedSopInstanceUid: string); + constructor( + affectedSopClassUid: string, + affectedSopInstanceUid: string, + metaSopClassUid?: string + ); } declare class NCreateResponse extends Response { @@ -1095,7 +1114,12 @@ declare class NActionRequest extends Request { /** * Creates an instance of NActionRequest. */ - constructor(requestedSopClassUid: string, requestedSopInstanceUid: string, actionTypeId: number); + constructor( + requestedSopClassUid: string, + requestedSopInstanceUid: string, + actionTypeId: number, + metaSopClassUid?: string + ); /** * Gets action type ID. @@ -1140,7 +1164,11 @@ declare class NDeleteRequest extends Request { /** * Creates an instance of NDeleteRequest. */ - constructor(requestedSopClassUid: string, requestedSopInstanceUid: string); + constructor( + requestedSopClassUid: string, + requestedSopInstanceUid: string, + metaSopClassUid?: string + ); } declare class NDeleteResponse extends Response { @@ -1164,7 +1192,12 @@ declare class NEventReportRequest extends Request { /** * Creates an instance of NEventReportRequest. */ - constructor(affectedSopClassUid: string, affectedSopInstanceUid: string, eventTypeID: number); + constructor( + affectedSopClassUid: string, + affectedSopInstanceUid: string, + eventTypeID: number, + metaSopClassUid?: string + ); /** * Gets event type ID. @@ -1212,7 +1245,8 @@ declare class NGetRequest extends Request { constructor( requestedSopClassUid: string, requestedSopInstanceUid: string, - attributeIdentifierList: Array + attributeIdentifierList: Array, + metaSopClassUid?: string ); /** @@ -1247,7 +1281,11 @@ declare class NSetRequest extends Request { /** * Creates an instance of NSetRequest. */ - constructor(requestedSopClassUid: string, requestedSopInstanceUid: string); + constructor( + requestedSopClassUid: string, + requestedSopInstanceUid: string, + metaSopClassUid?: string + ); } declare class NSetResponse extends Response { diff --git a/index.test-d.ts b/index.test-d.ts index f16d97d..4cde912 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -145,16 +145,19 @@ expectType(Implementation.getMaxPduLength()); expectError(Implementation.setMaxPduLength('1')); // Request -expectError(new Request('1', 123, 'true')); -expectType(new Request(1, '1.2.3.4.5', false)); +expectError(new Request('1', 123, 'true', 1)); +expectType(new Request(1, '1.2.3.4.5', false, '5.4.3.2.1')); -const request = new Request(1, '1.2.3.4.5', false); +const request = new Request(1, '1.2.3.4.5', false, '5.4.3.2.1'); expectType(request.getAffectedSopClassUid()); expectError(request.setAffectedSopClassUid(1)); expectType(request.setAffectedSopClassUid('1.2.3.4')); expectType(request.getRequestedSopClassUid()); expectError(request.setRequestedSopClassUid(1)); expectType(request.setRequestedSopClassUid('1.2.3.4')); +expectType(request.getMetaSopClassUid()); +expectError(request.setMetaSopClassUid(1)); +expectType(request.setRequestedSopClassUid('5.4.3.2.1')); expectType(request.getAffectedSopInstanceUid()); expectError(request.setAffectedSopInstanceUid(1)); expectType(request.setAffectedSopInstanceUid('1.2.3.4')); @@ -305,7 +308,10 @@ expectType(getResponse.getFailures()); // NCreateRequest expectError(new NCreateRequest(1)); expectError(new NCreateRequest('1', 2)); -expectType(new NCreateRequest(SopClass.BasicFilmBox, '1.2.3.4.5')); +expectError(new NCreateRequest('1', 2, 3)); +expectType( + new NCreateRequest(SopClass.BasicFilmBox, '1.2.3.4.5', '5.4.3.2.1') +); // NCreateResponse expectError(new NCreateResponse('1', 2, '3', 4)); @@ -315,13 +321,14 @@ expectType( // NActionRequest expectError(new NActionRequest(1)); -expectError(new NActionRequest('1', 2, '3')); +expectError(new NActionRequest('1', 2, '3', 1)); expectType( - new NActionRequest(SopClass.BasicFilmSession, '1.2.3.4.5', 0x01) + new NActionRequest(SopClass.BasicFilmSession, '1.2.3.4.5', 0x01, '5.4.3.2.1') ); const actionRequest = new NActionRequest(SopClass.PrintJob, '1.2.3.4.5', 0x01); expectType(actionRequest.getActionTypeId()); +expectType(actionRequest.getMetaSopClassUid()); expectError(actionRequest.setActionTypeId('1')); // NActionResponse @@ -345,7 +352,10 @@ expectError(actionResponse.setActionTypeId('1')); // NDeleteRequest expectError(new NDeleteRequest(1)); expectError(new NDeleteRequest('1', 2)); -expectType(new NDeleteRequest(SopClass.BasicFilmSession, '1.2.3.4.5')); +expectError(new NDeleteRequest('1', 2, 3)); +expectType( + new NDeleteRequest(SopClass.BasicFilmSession, '1.2.3.4.5', '5.4.3.2.1') +); // NDeleteResponse expectError(new NDeleteResponse('1', 2, '3', 4)); @@ -356,8 +366,9 @@ expectType( // NEventReportRequest expectError(new NEventReportRequest(1)); expectError(new NEventReportRequest('1', 2, '3')); +expectError(new NEventReportRequest('1', 2, '3', 4)); expectType( - new NEventReportRequest(SopClass.PrintJob, '1.2.3.4.5', 0x01) + new NEventReportRequest(SopClass.PrintJob, '1.2.3.4.5', 0x01, '5.4.3.2.1') ); const eventReportRequest = new NEventReportRequest(SopClass.PrintJob, '1.2.3.4.5', 0x01); @@ -385,14 +396,14 @@ expectError(eventReportResponse.setEventTypeId('1')); // NGetRequest expectError(new NGetRequest(1)); expectError(new NGetRequest('1', 2)); -expectError(new NGetRequest('1', 2, '3')); +expectError(new NGetRequest('1', 2, '3', 4)); expectType( - new NGetRequest(SopClass.BasicGrayscaleImageBox, '1.2.3.4.5', ['PatientID']) + new NGetRequest(SopClass.BasicGrayscaleImageBox, '1.2.3.4.5', ['PatientID'], '5.4.3.2.1') ); -const cGetRequest = new NGetRequest(SopClass.BasicGrayscaleImageBox, '1.2.3.4.5', ['PatientID']); -expectType>(cGetRequest.getAttributeIdentifierList()); -expectError(cGetRequest.setAttributeIdentifierList('1')); +const nGetRequest = new NGetRequest(SopClass.BasicGrayscaleImageBox, '1.2.3.4.5', ['PatientID']); +expectType>(nGetRequest.getAttributeIdentifierList()); +expectError(nGetRequest.setAttributeIdentifierList('1')); // NGetResponse expectError(new NGetResponse('1', 2, '3', 4)); @@ -405,7 +416,10 @@ expectType( // NSetRequest expectError(new NSetRequest(1)); expectError(new NSetRequest('1', 2)); -expectType(new NSetRequest(SopClass.BasicFilmSession, '1.2.3.4.5')); +expectError(new NSetRequest('1', 2, 3)); +expectType( + new NSetRequest(SopClass.BasicFilmSession, '1.2.3.4.5', undefined) +); // NSetResponse expectError(new NSetResponse('1', 2, '3', 4)); diff --git a/package-lock.json b/package-lock.json index 68b6f32..c71cd46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,40 +1,40 @@ { "name": "dcmjs-dimse", - "version": "0.1.28", + "version": "0.1.29", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dcmjs-dimse", - "version": "0.1.28", + "version": "0.1.29", "license": "MIT", "dependencies": { "async-eventemitter": "^0.2.4", "dcmjs": "^0.33.0", "smart-buffer": "^4.2.0", "ts-mixer": "^6.0.4", - "winston": "^3.13.1" + "winston": "^3.15.0" }, "devDependencies": { "@types/async-eventemitter": "^0.2.4", - "@types/node": "^20.14.11", + "@types/node": "^22.7.5", "c8": "^9.1.0", "chai": "^4.3.10", "docdash": "^2.0.2", "eslint": "^8.57.0", "jsdoc": "^4.0.3", - "mocha": "^10.6.0", - "mock-fs": "^5.2.0", - "nodemon": "^3.1.4", + "mocha": "^10.7.3", + "mock-fs": "^5.4.0", + "nodemon": "^3.1.7", "open-cli": "^7.2.0", "prettier": "^3.3.3", "selfsigned": "^2.4.1", "shx": "^0.3.3", "terser-webpack-plugin": "^5.3.10", "ts-node": "^10.9.2", - "tsd": "^0.31.1", - "typescript": "^5.5.3", - "webpack": "^5.93.0", + "tsd": "^0.31.2", + "typescript": "^5.1.3", + "webpack": "^5.95.0", "webpack-cli": "^5.1.4" }, "funding": { @@ -586,16 +586,6 @@ "@types/json-schema": "*" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -649,12 +639,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", - "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/node-forge": { @@ -1579,9 +1569,9 @@ } }, "node_modules/dcmjs": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/dcmjs/-/dcmjs-0.33.0.tgz", - "integrity": "sha512-8QfVA+TeuuKoVyhkJo/iCFDnpiNGDDrRQdM/tsi7gm1a/gNt4yYUBXLDho+CmVgvsaKccv7UMZBrGfmVDfNLvg==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/dcmjs/-/dcmjs-0.33.1.tgz", + "integrity": "sha512-/vwOPAX5fOQSwqf8t7bV7sy1h2h+gTWw5t/be8OIY7IwUpuKuKRChZvxINAjNZ9DDWHMB/uSOS7NJceu1YChfQ==", "dependencies": { "@babel/runtime-corejs3": "^7.22.5", "adm-zip": "^0.5.10", @@ -1788,9 +1778,9 @@ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -3713,9 +3703,9 @@ } }, "node_modules/mocha": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.6.0.tgz", - "integrity": "sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==", + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", + "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", "dev": true, "dependencies": { "ansi-colors": "^4.1.3", @@ -3847,9 +3837,9 @@ } }, "node_modules/mock-fs": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.2.0.tgz", - "integrity": "sha512-2dF2R6YMSZbpip1V1WHKGLNjr/k48uQClqMVb5H3MOvwc9qhYis3/IWbj02qIg/Y8MDXKFF4c5v0rxx2o6xTZw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.0.tgz", + "integrity": "sha512-3ROPnEMgBOkusBMYQUW2rnT3wZwsgfOKzJDLvx/TZ7FL1WmWvwSwn3j4aDR5fLDGtgcc1WF0Z1y0di7c9L4FKw==", "dev": true, "engines": { "node": ">=12.0.0" @@ -3897,9 +3887,9 @@ "dev": true }, "node_modules/nodemon": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", - "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", + "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", "dev": true, "dependencies": { "chokidar": "^3.5.2", @@ -5494,9 +5484,9 @@ } }, "node_modules/tsd": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.31.1.tgz", - "integrity": "sha512-sSL84A0SFwx2xGMWrxlGaarKFSQszWjJS2vgNDDLwatytzg2aq6ShlwHsBYxRNmjzXISODwMva5ZOdAg/4AoOA==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.31.2.tgz", + "integrity": "sha512-VplBAQwvYrHzVihtzXiUVXu5bGcr7uH1juQZ1lmKgkuGNGT+FechUCqmx9/zk7wibcqR2xaNEwCkDyKh+VVZnQ==", "dev": true, "dependencies": { "@tsd/typescript": "~5.4.3", @@ -5631,9 +5621,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5662,9 +5652,9 @@ "dev": true }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, "node_modules/unique-string": { @@ -5779,12 +5769,11 @@ } }, "node_modules/webpack": { - "version": "5.93.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", - "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "dev": true, "dependencies": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", @@ -5793,7 +5782,7 @@ "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -5967,9 +5956,9 @@ "dev": true }, "node_modules/winston": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.1.tgz", - "integrity": "sha512-SvZit7VFNvXRzbqGHsv5KSmgbEYR5EiQfDAL9gxYkRqa934Hnk++zze0wANKtMHcy/gI4W/3xmSDwlhf865WGw==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.15.0.tgz", + "integrity": "sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow==", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", @@ -6564,16 +6553,6 @@ "@types/json-schema": "*" } }, - "@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", @@ -6627,12 +6606,12 @@ "dev": true }, "@types/node": { - "version": "20.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", - "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, "requires": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "@types/node-forge": { @@ -7349,9 +7328,9 @@ } }, "dcmjs": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/dcmjs/-/dcmjs-0.33.0.tgz", - "integrity": "sha512-8QfVA+TeuuKoVyhkJo/iCFDnpiNGDDrRQdM/tsi7gm1a/gNt4yYUBXLDho+CmVgvsaKccv7UMZBrGfmVDfNLvg==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/dcmjs/-/dcmjs-0.33.1.tgz", + "integrity": "sha512-/vwOPAX5fOQSwqf8t7bV7sy1h2h+gTWw5t/be8OIY7IwUpuKuKRChZvxINAjNZ9DDWHMB/uSOS7NJceu1YChfQ==", "requires": { "@babel/runtime-corejs3": "^7.22.5", "adm-zip": "^0.5.10", @@ -7501,9 +7480,9 @@ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -8879,9 +8858,9 @@ "dev": true }, "mocha": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.6.0.tgz", - "integrity": "sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==", + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", + "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", "dev": true, "requires": { "ansi-colors": "^4.1.3", @@ -8987,9 +8966,9 @@ } }, "mock-fs": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.2.0.tgz", - "integrity": "sha512-2dF2R6YMSZbpip1V1WHKGLNjr/k48uQClqMVb5H3MOvwc9qhYis3/IWbj02qIg/Y8MDXKFF4c5v0rxx2o6xTZw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.4.0.tgz", + "integrity": "sha512-3ROPnEMgBOkusBMYQUW2rnT3wZwsgfOKzJDLvx/TZ7FL1WmWvwSwn3j4aDR5fLDGtgcc1WF0Z1y0di7c9L4FKw==", "dev": true }, "ms": { @@ -9031,9 +9010,9 @@ "dev": true }, "nodemon": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", - "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", + "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", "dev": true, "requires": { "chokidar": "^3.5.2", @@ -10127,9 +10106,9 @@ } }, "tsd": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.31.1.tgz", - "integrity": "sha512-sSL84A0SFwx2xGMWrxlGaarKFSQszWjJS2vgNDDLwatytzg2aq6ShlwHsBYxRNmjzXISODwMva5ZOdAg/4AoOA==", + "version": "0.31.2", + "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.31.2.tgz", + "integrity": "sha512-VplBAQwvYrHzVihtzXiUVXu5bGcr7uH1juQZ1lmKgkuGNGT+FechUCqmx9/zk7wibcqR2xaNEwCkDyKh+VVZnQ==", "dev": true, "requires": { "@tsd/typescript": "~5.4.3", @@ -10224,9 +10203,9 @@ "dev": true }, "typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true }, "uc.micro": { @@ -10248,9 +10227,9 @@ "dev": true }, "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, "unique-string": { @@ -10330,12 +10309,11 @@ } }, "webpack": { - "version": "5.93.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", - "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "dev": true, "requires": { - "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", @@ -10344,7 +10322,7 @@ "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -10456,9 +10434,9 @@ "dev": true }, "winston": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.1.tgz", - "integrity": "sha512-SvZit7VFNvXRzbqGHsv5KSmgbEYR5EiQfDAL9gxYkRqa934Hnk++zze0wANKtMHcy/gI4W/3xmSDwlhf865WGw==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.15.0.tgz", + "integrity": "sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow==", "requires": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", diff --git a/package.json b/package.json index 51ae6a2..756ed64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dcmjs-dimse", - "version": "0.1.28", + "version": "0.1.29", "description": "DICOM DIMSE implementation for Node.js using dcmjs", "main": "build/dcmjs-dimse.min.js", "module": "build/dcmjs-dimse.min.js", @@ -47,28 +47,28 @@ "dcmjs": "^0.33.0", "smart-buffer": "^4.2.0", "ts-mixer": "^6.0.4", - "winston": "^3.13.1" + "winston": "^3.15.0" }, "devDependencies": { "@types/async-eventemitter": "^0.2.4", - "@types/node": "^20.14.11", + "@types/node": "^22.7.5", "c8": "^9.1.0", "chai": "^4.3.10", "docdash": "^2.0.2", "eslint": "^8.57.0", "jsdoc": "^4.0.3", - "mocha": "^10.6.0", - "mock-fs": "^5.2.0", - "nodemon": "^3.1.4", + "mocha": "^10.7.3", + "mock-fs": "^5.4.0", + "nodemon": "^3.1.7", "open-cli": "^7.2.0", "prettier": "^3.3.3", "selfsigned": "^2.4.1", "shx": "^0.3.3", "terser-webpack-plugin": "^5.3.10", "ts-node": "^10.9.2", - "tsd": "^0.31.1", - "typescript": "^5.5.3", - "webpack": "^5.93.0", + "tsd": "^0.31.2", + "typescript": "^5.6.3", + "webpack": "^5.95.0", "webpack-cli": "^5.1.4" } } diff --git a/src/Association.js b/src/Association.js index b0bfc90..324e482 100644 --- a/src/Association.js +++ b/src/Association.js @@ -738,7 +738,6 @@ class Association { context.getAbstractSyntaxUid() }` ); - const syntaxes = context.getTransferSyntaxUids(); syntaxes.forEach((tx) => { str.push(` Transfer: ${this._uidNameFromValue(TransferSyntax, tx) || tx}`); @@ -776,15 +775,20 @@ class Association { case CommandFieldType.NSetRequest: case CommandFieldType.NActionRequest: case CommandFieldType.NDeleteRequest: - return request.getRequestedSopClassUid(); + return request.getMetaSopClassUid() !== undefined + ? request.getMetaSopClassUid() + : request.getRequestedSopClassUid(); case CommandFieldType.CStoreRequest: case CommandFieldType.CFindRequest: case CommandFieldType.CGetRequest: case CommandFieldType.CMoveRequest: case CommandFieldType.CEchoRequest: + return request.getAffectedSopClassUid(); case CommandFieldType.NEventReportRequest: case CommandFieldType.NCreateRequest: - return request.getAffectedSopClassUid(); + return request.getMetaSopClassUid() !== undefined + ? request.getMetaSopClassUid() + : request.getAffectedSopClassUid(); default: return request.getAffectedSopClassUid(); } diff --git a/src/Command.js b/src/Command.js index 486ed68..9f3b2cc 100644 --- a/src/Command.js +++ b/src/Command.js @@ -179,8 +179,9 @@ class Request extends Mixin(Command, AsyncEventEmitter) { * @param {number} type - Command field type. * @param {string} affectedOrRequestedClassUid - Affected or requested SOP Class UID. * @param {boolean} hasDataset - Request has dataset. + * @param {string} [metaSopClassUid] - Meta SOP Class UID. */ - constructor(type, affectedOrRequestedClassUid, hasDataset) { + constructor(type, affectedOrRequestedClassUid, hasDataset, metaSopClassUid) { super( new Dataset({ CommandField: type, @@ -198,6 +199,7 @@ class Request extends Mixin(Command, AsyncEventEmitter) { this.setAffectedSopClassUid(affectedOrRequestedClassUid); break; } + this.metaSopClassUid = metaSopClassUid; } /** @@ -240,6 +242,24 @@ class Request extends Mixin(Command, AsyncEventEmitter) { command.setElement('RequestedSOPClassUID', requestedSopClassUid); } + /** + * Gets meta SOP class UID. + * @method + * @returns {string} Meta SOP class UID. + */ + getMetaSopClassUid() { + return this.metaSopClassUid; + } + + /** + * Sets meta SOP class UID. + * @method + * @param {string} metaSopClassUid - Meta SOP class UID. + */ + setMetaSopClassUid(metaSopClassUid) { + this.metaSopClassUid = metaSopClassUid; + } + /** * Gets affected SOP instance UID. * @method @@ -1377,10 +1397,12 @@ class NCreateRequest extends Request { * @constructor * @param {string} affectedSopClassUid - Affected SOP Class UID. * @param {string} affectedSopInstanceUid - Affected SOP Instance UID. + * @param {string} [metaSopClassUid] - Meta SOP Class UID. */ - constructor(affectedSopClassUid, affectedSopInstanceUid) { + constructor(affectedSopClassUid, affectedSopInstanceUid, metaSopClassUid) { super(CommandFieldType.NCreateRequest, affectedSopClassUid, false); this.setAffectedSopInstanceUid(affectedSopInstanceUid); + this.setMetaSopClassUid(metaSopClassUid); } } //#endregion @@ -1432,11 +1454,13 @@ class NActionRequest extends Request { * @param {string} requestedSopClassUid - Requested SOP Class UID. * @param {string} requestedSopInstanceUid - Requested SOP Instance UID. * @param {number} actionTypeId - Action type ID. + * @param {string} [metaSopClassUid] - Meta SOP Class UID. */ - constructor(requestedSopClassUid, requestedSopInstanceUid, actionTypeId) { + constructor(requestedSopClassUid, requestedSopInstanceUid, actionTypeId, metaSopClassUid) { super(CommandFieldType.NActionRequest, requestedSopClassUid, false); this.setRequestedSopInstanceUid(requestedSopInstanceUid); this.setActionTypeId(actionTypeId); + this.setMetaSopClassUid(metaSopClassUid); } /** @@ -1530,10 +1554,12 @@ class NDeleteRequest extends Request { * @constructor * @param {string} requestedSopClassUid - Requested SOP Class UID. * @param {string} requestedSopInstanceUid - Requested SOP Instance UID. + * @param {string} [metaSopClassUid] - Meta SOP Class UID. */ - constructor(requestedSopClassUid, requestedSopInstanceUid) { + constructor(requestedSopClassUid, requestedSopInstanceUid, metaSopClassUid) { super(CommandFieldType.NDeleteRequest, requestedSopClassUid, false); this.setRequestedSopInstanceUid(requestedSopInstanceUid); + this.setMetaSopClassUid(metaSopClassUid); } } //#endregion @@ -1585,11 +1611,13 @@ class NEventReportRequest extends Request { * @param {string} affectedSopClassUid - Affected SOP Class UID. * @param {string} affectedSopInstanceUid - Affected SOP Instance UID. * @param {number} eventTypeID - Event type ID. + * @param {string} [metaSopClassUid] - Meta SOP Class UID. */ - constructor(affectedSopClassUid, affectedSopInstanceUid, eventTypeID) { + constructor(affectedSopClassUid, affectedSopInstanceUid, eventTypeID, metaSopClassUid) { super(CommandFieldType.NEventReportRequest, affectedSopClassUid, false); this.setAffectedSopInstanceUid(affectedSopInstanceUid); this.setEventTypeId(eventTypeID); + this.setMetaSopClassUid(metaSopClassUid); } /** @@ -1684,13 +1712,20 @@ class NGetRequest extends Request { * @param {string} requestedSopClassUid - Requested SOP Class UID. * @param {string} requestedSopInstanceUid - Requested SOP Instance UID. * @param {Array} attributeIdentifierList - The requested attributes identifier list. + * @param {string} [metaSopClassUid] - Meta SOP Class UID. */ - constructor(requestedSopClassUid, requestedSopInstanceUid, attributeIdentifierList) { + constructor( + requestedSopClassUid, + requestedSopInstanceUid, + attributeIdentifierList, + metaSopClassUid + ) { super(CommandFieldType.NGetRequest, requestedSopClassUid, false); this.setRequestedSopInstanceUid(requestedSopInstanceUid); this.setAttributeIdentifierList( !Array.isArray(attributeIdentifierList) ? [attributeIdentifierList] : attributeIdentifierList ); + this.setMetaSopClassUid(metaSopClassUid); } /** @@ -1805,10 +1840,12 @@ class NSetRequest extends Request { * @constructor * @param {string} requestedSopClassUid - Requested SOP Class UID. * @param {string} requestedSopInstanceUid - Requested SOP Instance UID. + * @param {string} [metaSopClassUid] - Meta SOP Class UID. */ - constructor(requestedSopClassUid, requestedSopInstanceUid) { + constructor(requestedSopClassUid, requestedSopInstanceUid, metaSopClassUid) { super(CommandFieldType.NSetRequest, requestedSopClassUid, false); this.setRequestedSopInstanceUid(requestedSopInstanceUid); + this.setMetaSopClassUid(metaSopClassUid); } } //#endregion diff --git a/src/version.js b/src/version.js index 5616609..d7f4f02 100644 --- a/src/version.js +++ b/src/version.js @@ -1 +1 @@ -module.exports = '0.1.28'; +module.exports = '0.1.29'; diff --git a/test/Association.test.js b/test/Association.test.js index e663fd9..5d44327 100644 --- a/test/Association.test.js +++ b/test/Association.test.js @@ -1,5 +1,11 @@ const { Association } = require('./../src/Association'); -const { CGetRequest, CStoreRequest, Request } = require('./../src/Command'); +const { + CGetRequest, + CStoreRequest, + NCreateRequest, + NDeleteRequest, + Request, +} = require('./../src/Command'); const { CommandFieldType, PresentationContextResult, @@ -271,4 +277,42 @@ describe('Association', () => { ...Object.values(StorageClass), ]); }); + + it('should correctly add presentation contexts with meta SOP classes', () => { + const callingAet = 'CALLINGAET'; + const calledAet = 'CALLEDAET'; + + const association = new Association(callingAet, calledAet); + association.addPresentationContext(SopClass.BasicGrayscalePrintManagementMeta); + let pcId = association.addPresentationContextFromRequest( + new NCreateRequest( + SopClass.BasicFilmSession, + Dataset.generateDerivedUid(), + SopClass.BasicGrayscalePrintManagementMeta + ) + ); + pcId = association.addPresentationContextFromRequest( + new NCreateRequest( + SopClass.BasicFilmBox, + Dataset.generateDerivedUid(), + SopClass.BasicGrayscalePrintManagementMeta + ) + ); + pcId = association.addPresentationContextFromRequest( + new NDeleteRequest( + SopClass.BasicFilmBox, + Dataset.generateDerivedUid(), + SopClass.BasicGrayscalePrintManagementMeta + ) + ); + pcId = association.addPresentationContextFromRequest( + new NDeleteRequest( + SopClass.BasicFilmSession, + Dataset.generateDerivedUid(), + SopClass.BasicGrayscalePrintManagementMeta + ) + ); + + expect(association.getPresentationContexts().length).to.be.eq(1); + }); }); diff --git a/test/Commands.test.js b/test/Commands.test.js index 78fadfb..8e99d21 100644 --- a/test/Commands.test.js +++ b/test/Commands.test.js @@ -55,13 +55,24 @@ describe('Command', () => { }); it('should correctly create a request', () => { - const uid = Dataset.generateDerivedUid(); - const request = new Request(1, uid, 2, true); - const commandDataset = request.getCommandDataset(); - - expect(request.getAffectedSopClassUid()).to.be.eq(uid); - expect(request.hasDataset()).to.be.true; - expect(commandDataset.getElement('CommandField')).to.be.eq(1); + const uid1 = Dataset.generateDerivedUid(); + const request1 = new Request(1, uid1, true); + const commandDataset1 = request1.getCommandDataset(); + + const uid2 = Dataset.generateDerivedUid(); + const uid3 = Dataset.generateDerivedUid(); + const request2 = new Request(2, uid2, false, uid3); + const commandDataset2 = request2.getCommandDataset(); + + expect(request1.getAffectedSopClassUid()).to.be.eq(uid1); + expect(request1.getMetaSopClassUid()).to.be.undefined; + expect(request1.hasDataset()).to.be.true; + expect(commandDataset1.getElement('CommandField')).to.be.eq(1); + + expect(request2.getAffectedSopClassUid()).to.be.eq(uid2); + expect(request2.getMetaSopClassUid()).to.be.eq(uid3); + expect(request2.hasDataset()).to.be.false; + expect(commandDataset2.getElement('CommandField')).to.be.eq(2); }); it('should correctly create a response', () => { @@ -257,9 +268,11 @@ describe('Command', () => { it('should correctly create a N-CREATE request', () => { const sopClassUid = Dataset.generateDerivedUid(); const sopInstanceUid = Dataset.generateDerivedUid(); - const request = new NCreateRequest(sopClassUid, sopInstanceUid); + const metaSopClassUid = Dataset.generateDerivedUid(); + const request = new NCreateRequest(sopClassUid, sopInstanceUid, metaSopClassUid); expect(request.getAffectedSopClassUid()).to.be.eq(sopClassUid); + expect(request.getMetaSopClassUid()).to.be.eq(metaSopClassUid); expect(request.getAffectedSopInstanceUid()).to.be.eq(sopInstanceUid); expect(request.getCommandFieldType()).to.be.eq(CommandFieldType.NCreateRequest); expect(request.hasDataset()).to.be.false; @@ -290,6 +303,7 @@ describe('Command', () => { const request = new NActionRequest(sopClassUid, sopInstanceUid, 0x0001); expect(request.getRequestedSopClassUid()).to.be.eq(sopClassUid); + expect(request.getMetaSopClassUid()).to.be.undefined; expect(request.getRequestedSopInstanceUid()).to.be.eq(sopInstanceUid); expect(request.getActionTypeId()).to.be.eq(0x0001); expect(request.getCommandFieldType()).to.be.eq(CommandFieldType.NActionRequest); @@ -324,9 +338,11 @@ describe('Command', () => { it('should correctly create a N-DELETE request', () => { const sopClassUid = Dataset.generateDerivedUid(); const sopInstanceUid = Dataset.generateDerivedUid(); - const request = new NDeleteRequest(sopClassUid, sopInstanceUid); + const metaSopClassUid = Dataset.generateDerivedUid(); + const request = new NDeleteRequest(sopClassUid, sopInstanceUid, metaSopClassUid); expect(request.getRequestedSopClassUid()).to.be.eq(sopClassUid); + expect(request.getMetaSopClassUid()).to.be.eq(metaSopClassUid); expect(request.getRequestedSopInstanceUid()).to.be.eq(sopInstanceUid); expect(request.getCommandFieldType()).to.be.eq(CommandFieldType.NDeleteRequest); expect(request.hasDataset()).to.be.false; @@ -354,9 +370,11 @@ describe('Command', () => { it('should correctly create a N-EVENT-REPORT request', () => { const sopClassUid = Dataset.generateDerivedUid(); const sopInstanceUid = Dataset.generateDerivedUid(); - const request = new NEventReportRequest(sopClassUid, sopInstanceUid, 0x0001); + const metaSopClassUid = Dataset.generateDerivedUid(); + const request = new NEventReportRequest(sopClassUid, sopInstanceUid, 0x0001, metaSopClassUid); expect(request.getAffectedSopClassUid()).to.be.eq(sopClassUid); + expect(request.getMetaSopClassUid()).to.be.eq(metaSopClassUid); expect(request.getAffectedSopInstanceUid()).to.be.eq(sopInstanceUid); expect(request.getEventTypeId()).to.be.eq(0x0001); expect(request.getCommandFieldType()).to.be.eq(CommandFieldType.NEventReportRequest); @@ -412,6 +430,7 @@ describe('Command', () => { const request = new NGetRequest(sopClassUid, sopInstanceUid, attributeIdentifierList); expect(request.getRequestedSopClassUid()).to.be.eq(sopClassUid); + expect(request.getMetaSopClassUid()).to.be.undefined; expect(request.getRequestedSopInstanceUid()).to.be.eq(sopInstanceUid); expect(request.getAttributeIdentifierList()).to.have.members(attributeIdentifierList); expect(request.getCommandFieldType()).to.be.eq(CommandFieldType.NGetRequest); @@ -442,9 +461,11 @@ describe('Command', () => { it('should correctly create a N-SET request', () => { const sopClassUid = Dataset.generateDerivedUid(); const sopInstanceUid = Dataset.generateDerivedUid(); - const request = new NSetRequest(sopClassUid, sopInstanceUid); + const metaSopClassUid = Dataset.generateDerivedUid(); + const request = new NSetRequest(sopClassUid, sopInstanceUid, metaSopClassUid); expect(request.getRequestedSopClassUid()).to.be.eq(sopClassUid); + expect(request.getMetaSopClassUid()).to.be.eq(metaSopClassUid); expect(request.getRequestedSopInstanceUid()).to.be.eq(sopInstanceUid); expect(request.getCommandFieldType()).to.be.eq(CommandFieldType.NSetRequest); expect(request.hasDataset()).to.be.false;