fhirsmith 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/FHIRsmith.png +0 -0
- package/README.md +277 -0
- package/config-template.json +144 -0
- package/library/folder-setup.js +58 -0
- package/library/html-server.js +166 -0
- package/library/html.js +835 -0
- package/library/i18nsupport.js +259 -0
- package/library/languages.js +779 -0
- package/library/logger-telnet.js +205 -0
- package/library/logger.js +279 -0
- package/library/package-manager.js +876 -0
- package/library/utilities.js +196 -0
- package/library/version-utilities.js +1056 -0
- package/npmprojector/config-example.json +13 -0
- package/npmprojector/indexer.js +394 -0
- package/npmprojector/npmprojector.js +395 -0
- package/npmprojector/readme.md +174 -0
- package/npmprojector/watcher.js +335 -0
- package/package.json +119 -0
- package/packages/package-crawler.js +846 -0
- package/packages/packages-template.html +126 -0
- package/packages/packages.js +2838 -0
- package/passwords.ini +2 -0
- package/publisher/publisher-template.html +208 -0
- package/publisher/publisher.js +2167 -0
- package/publisher/task-draft.js +458 -0
- package/registry/api.js +735 -0
- package/registry/crawler.js +637 -0
- package/registry/model.js +513 -0
- package/registry/readme.md +243 -0
- package/registry/registry-data.json +121015 -0
- package/registry/registry-template.html +126 -0
- package/registry/registry.js +1395 -0
- package/registry/test-runner.js +237 -0
- package/root-template.html +124 -0
- package/server.js +524 -0
- package/shl/private-key.pem +5 -0
- package/shl/public-key.pem +18 -0
- package/shl/shl.js +1125 -0
- package/shl/vhl.js +69 -0
- package/static/FHIRsmith128.png +0 -0
- package/static/FHIRsmith16.png +0 -0
- package/static/FHIRsmith32.png +0 -0
- package/static/FHIRsmith64.png +0 -0
- package/static/assets/css/bootstrap-fhir.css +5302 -0
- package/static/assets/css/bootstrap-glyphicons.css +2 -0
- package/static/assets/css/bootstrap.css +4097 -0
- package/static/assets/css/jquery-ui.css +523 -0
- package/static/assets/css/jquery-ui.structure.css +863 -0
- package/static/assets/css/jquery-ui.structure.min.css +5 -0
- package/static/assets/css/jquery-ui.theme.css +439 -0
- package/static/assets/css/jquery-ui.theme.min.css +5 -0
- package/static/assets/css/jquery.ui.all.css +7 -0
- package/static/assets/css/modules.css +18 -0
- package/static/assets/css/project.css +367 -0
- package/static/assets/css/pygments-manni.css +66 -0
- package/static/assets/css/tags.css +74 -0
- package/static/assets/css/xml.css +2 -0
- package/static/assets/fonts/glyphiconshalflings-regular.eot +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.otf +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.svg +175 -0
- package/static/assets/fonts/glyphiconshalflings-regular.ttf +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.woff +0 -0
- package/static/assets/ico/apple-touch-icon-114-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-144-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-57-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-72-precomposed.png +0 -0
- package/static/assets/ico/favicon.ico +0 -0
- package/static/assets/ico/favicon.png +0 -0
- package/static/assets/images/fhir-logo-www.png +0 -0
- package/static/assets/images/fhir-logo.png +0 -0
- package/static/assets/images/hl7-logo.png +0 -0
- package/static/assets/images/logo_ansinew.jpg +0 -0
- package/static/assets/images/search.png +0 -0
- package/static/assets/images/stripe.png +0 -0
- package/static/assets/images/target.png +0 -0
- package/static/assets/images/tx-registry-root.gif +0 -0
- package/static/assets/images/tx-registry.png +0 -0
- package/static/assets/images/tx-server.png +0 -0
- package/static/assets/images/tx-version.png +0 -0
- package/static/assets/js/bootstrap.min.js +6 -0
- package/static/assets/js/fhir-gw.js +259 -0
- package/static/assets/js/fhir.js +2 -0
- package/static/assets/js/html5shiv.js +8 -0
- package/static/assets/js/jcookie.js +96 -0
- package/static/assets/js/jquery-ui.min.js +6 -0
- package/static/assets/js/jquery.js +10716 -0
- package/static/assets/js/jquery.min.js +2 -0
- package/static/assets/js/jquery.ui.core.js +314 -0
- package/static/assets/js/jquery.ui.draggable.js +825 -0
- package/static/assets/js/jquery.ui.mouse.js +162 -0
- package/static/assets/js/jquery.ui.resizable.js +842 -0
- package/static/assets/js/jquery.ui.widget.js +268 -0
- package/static/assets/js/json2.js +487 -0
- package/static/assets/js/jtip.js +97 -0
- package/static/assets/js/respond.min.js +6 -0
- package/static/assets/js/statuspage.js +70 -0
- package/static/assets/js/xml.js +2 -0
- package/static/dist/js/bootstrap.js +1964 -0
- package/static/favicon.png +0 -0
- package/static/fhir.css +626 -0
- package/static/icon-fhir-16.png +0 -0
- package/static/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- package/static/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- package/static/images/ui-bg_flat_10_000000_40x100.png +0 -0
- package/static/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- package/static/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- package/static/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- package/static/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- package/static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- package/static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- package/static/images/ui-icons_222222_256x240.png +0 -0
- package/static/images/ui-icons_228ef1_256x240.png +0 -0
- package/static/images/ui-icons_ef8c08_256x240.png +0 -0
- package/static/images/ui-icons_ffd27a_256x240.png +0 -0
- package/static/images/ui-icons_ffffff_256x240.png +0 -0
- package/static/js/jquery.effects.blind.js +49 -0
- package/static/js/jquery.effects.bounce.js +78 -0
- package/static/js/jquery.effects.clip.js +54 -0
- package/static/js/jquery.effects.core.js +763 -0
- package/static/js/jquery.effects.drop.js +50 -0
- package/static/js/jquery.effects.explode.js +79 -0
- package/static/js/jquery.effects.fade.js +32 -0
- package/static/js/jquery.effects.fold.js +56 -0
- package/static/js/jquery.effects.highlight.js +50 -0
- package/static/js/jquery.effects.pulsate.js +51 -0
- package/static/js/jquery.effects.scale.js +178 -0
- package/static/js/jquery.effects.shake.js +57 -0
- package/static/js/jquery.effects.slide.js +50 -0
- package/static/js/jquery.effects.transfer.js +45 -0
- package/static/js/jquery.ui.accordion.js +611 -0
- package/static/js/jquery.ui.autocomplete.js +612 -0
- package/static/js/jquery.ui.button.js +416 -0
- package/static/js/jquery.ui.datepicker.js +1823 -0
- package/static/js/jquery.ui.dialog.js +878 -0
- package/static/js/jquery.ui.droppable.js +296 -0
- package/static/js/jquery.ui.position.js +252 -0
- package/static/js/jquery.ui.progressbar.js +109 -0
- package/static/js/jquery.ui.selectable.js +266 -0
- package/static/js/jquery.ui.slider.js +666 -0
- package/static/js/jquery.ui.sortable.js +1077 -0
- package/static/js/jquery.ui.tabs.js +758 -0
- package/stats.js +80 -0
- package/test-cache/vsac/vsac-valuesets.db +0 -0
- package/token/nginx_passport_setup.md +383 -0
- package/token/security_guide.md +294 -0
- package/token/token-template.html +330 -0
- package/token/token.js +1300 -0
- package/translations/Messages.properties +1510 -0
- package/translations/Messages_ar.properties +1399 -0
- package/translations/Messages_de.properties +836 -0
- package/translations/Messages_es.properties +737 -0
- package/translations/Messages_fr.properties +1 -0
- package/translations/Messages_ja.properties +893 -0
- package/translations/Messages_nl.properties +1357 -0
- package/translations/Messages_pt.properties +1302 -0
- package/translations/Messages_ru.properties +1 -0
- package/translations/Messages_uz.properties +1 -0
- package/translations/Messages_zh.properties +1 -0
- package/translations/rendering-phrases.properties +1128 -0
- package/translations/rendering-phrases_ar.properties +1091 -0
- package/translations/rendering-phrases_de.properties +6 -0
- package/translations/rendering-phrases_es.properties +6 -0
- package/translations/rendering-phrases_fr.properties +624 -0
- package/translations/rendering-phrases_ja.properties +21 -0
- package/translations/rendering-phrases_nl.properties +970 -0
- package/translations/rendering-phrases_pt.properties +1020 -0
- package/translations/rendering-phrases_ru.properties +1094 -0
- package/translations/rendering-phrases_uz.properties +1 -0
- package/translations/rendering-phrases_zh.properties +1 -0
- package/tx/README.md +418 -0
- package/tx/cm/cm-api.js +110 -0
- package/tx/cm/cm-database.js +735 -0
- package/tx/cm/cm-package.js +325 -0
- package/tx/cs/cs-api.js +789 -0
- package/tx/cs/cs-areacode.js +615 -0
- package/tx/cs/cs-country.js +1110 -0
- package/tx/cs/cs-cpt.js +785 -0
- package/tx/cs/cs-cs.js +1579 -0
- package/tx/cs/cs-currency.js +539 -0
- package/tx/cs/cs-db.js +1321 -0
- package/tx/cs/cs-hgvs.js +329 -0
- package/tx/cs/cs-lang.js +465 -0
- package/tx/cs/cs-loinc.js +1485 -0
- package/tx/cs/cs-mimetypes.js +238 -0
- package/tx/cs/cs-ndc.js +704 -0
- package/tx/cs/cs-omop.js +1025 -0
- package/tx/cs/cs-provider-api.js +43 -0
- package/tx/cs/cs-provider-list.js +37 -0
- package/tx/cs/cs-rxnorm.js +808 -0
- package/tx/cs/cs-snomed.js +1102 -0
- package/tx/cs/cs-ucum.js +514 -0
- package/tx/cs/cs-unii.js +271 -0
- package/tx/cs/cs-uri.js +218 -0
- package/tx/cs/cs-usstates.js +305 -0
- package/tx/dev.fhir.org.yml +14 -0
- package/tx/fixtures/test-cases-setup.json +18 -0
- package/tx/fixtures/test-cases.yml +16 -0
- package/tx/html/codesystem-operations.liquid +25 -0
- package/tx/html/home-metrics.liquid +247 -0
- package/tx/html/operations-form.liquid +148 -0
- package/tx/html/search-form.liquid +62 -0
- package/tx/html/tx-template.html +133 -0
- package/tx/html/valueset-operations.liquid +54 -0
- package/tx/importers/atc-to-fhir.js +316 -0
- package/tx/importers/import-loinc.module.js +1536 -0
- package/tx/importers/import-ndc.module.js +1088 -0
- package/tx/importers/import-rxnorm.module.js +898 -0
- package/tx/importers/import-sct.module.js +2457 -0
- package/tx/importers/import-unii.module.js +601 -0
- package/tx/importers/readme.md +453 -0
- package/tx/importers/subset-loinc.module.js +1081 -0
- package/tx/importers/subset-rxnorm.module.js +938 -0
- package/tx/importers/tx-import-base.js +351 -0
- package/tx/importers/tx-import-settings.js +310 -0
- package/tx/importers/tx-import.js +357 -0
- package/tx/library/canonical-resource.js +88 -0
- package/tx/library/capabilitystatement.js +292 -0
- package/tx/library/codesystem.js +774 -0
- package/tx/library/conceptmap.js +568 -0
- package/tx/library/designations.js +932 -0
- package/tx/library/errors.js +77 -0
- package/tx/library/extensions.js +117 -0
- package/tx/library/namingsystem.js +322 -0
- package/tx/library/operation-outcome.js +127 -0
- package/tx/library/parameters.js +105 -0
- package/tx/library/renderer.js +1559 -0
- package/tx/library/terminologycapabilities.js +418 -0
- package/tx/library/ucum-parsers.js +1029 -0
- package/tx/library/ucum-service.js +370 -0
- package/tx/library/ucum-types.js +1099 -0
- package/tx/library/valueset.js +543 -0
- package/tx/library.js +676 -0
- package/tx/ocl/cm-ocl.js +106 -0
- package/tx/ocl/cs-ocl.js +39 -0
- package/tx/ocl/vs-ocl.js +105 -0
- package/tx/operation-context.js +568 -0
- package/tx/params.js +613 -0
- package/tx/provider.js +403 -0
- package/tx/sct/ecl.js +1560 -0
- package/tx/sct/expressions.js +2077 -0
- package/tx/sct/structures.js +1396 -0
- package/tx/tx-html.js +1063 -0
- package/tx/tx.fhir.org.yml +39 -0
- package/tx/tx.js +927 -0
- package/tx/vs/vs-api.js +112 -0
- package/tx/vs/vs-database.js +786 -0
- package/tx/vs/vs-package.js +358 -0
- package/tx/vs/vs-vsac.js +366 -0
- package/tx/workers/batch-validate.js +129 -0
- package/tx/workers/batch.js +361 -0
- package/tx/workers/closure.js +32 -0
- package/tx/workers/expand.js +1845 -0
- package/tx/workers/lookup.js +407 -0
- package/tx/workers/metadata.js +467 -0
- package/tx/workers/operations.js +34 -0
- package/tx/workers/read.js +164 -0
- package/tx/workers/search.js +384 -0
- package/tx/workers/subsumes.js +334 -0
- package/tx/workers/translate.js +492 -0
- package/tx/workers/validate.js +2504 -0
- package/tx/workers/worker.js +904 -0
- package/tx/xml/capabilitystatement-xml.js +63 -0
- package/tx/xml/codesystem-xml.js +62 -0
- package/tx/xml/conceptmap-xml.js +65 -0
- package/tx/xml/namingsystem-xml.js +65 -0
- package/tx/xml/operationoutcome-xml.js +127 -0
- package/tx/xml/parameters-xml.js +312 -0
- package/tx/xml/terminologycapabilities-xml.js +64 -0
- package/tx/xml/valueset-xml.js +64 -0
- package/tx/xml/xml-base.js +603 -0
- package/vcl/vcl-parser.js +1098 -0
- package/vcl/vcl.js +253 -0
- package/windows-install.js +19 -0
- package/xig/xig-template.html +124 -0
- package/xig/xig.js +3049 -0
package/vcl/vcl.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025, Health Intersections Pty Ltd (http://www.healthintersections.com.au)
|
|
3
|
+
//
|
|
4
|
+
// Licensed under BSD-3: https://opensource.org/license/bsd-3-clause
|
|
5
|
+
//
|
|
6
|
+
|
|
7
|
+
const express = require('express');
|
|
8
|
+
const {parseVCLAndSetId, validateVCLExpression, VCLParseException} = require('./vcl-parser.js');
|
|
9
|
+
|
|
10
|
+
const Logger = require('../library/logger');
|
|
11
|
+
const vclLog = Logger.getInstance().child({ module: 'vcl' });
|
|
12
|
+
|
|
13
|
+
class VCLModule {
|
|
14
|
+
constructor(stats) {
|
|
15
|
+
this.router = express.Router();
|
|
16
|
+
this.config = null;
|
|
17
|
+
this.setupSecurityMiddleware();
|
|
18
|
+
this.setupRoutes();
|
|
19
|
+
this.stats = stats;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setupSecurityMiddleware() {
|
|
23
|
+
// Security headers middleware
|
|
24
|
+
this.router.use((req, res, next) => {
|
|
25
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
26
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
27
|
+
res.setHeader('X-XSS-Protection', '1; mode=block');
|
|
28
|
+
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
29
|
+
res.setHeader('Content-Security-Policy', [
|
|
30
|
+
"default-src 'self'",
|
|
31
|
+
"script-src 'self' 'unsafe-inline'",
|
|
32
|
+
"style-src 'self' 'unsafe-inline'",
|
|
33
|
+
"img-src 'self' data: https:",
|
|
34
|
+
"font-src 'self'",
|
|
35
|
+
"connect-src 'self'",
|
|
36
|
+
"frame-ancestors 'none'"
|
|
37
|
+
].join('; '));
|
|
38
|
+
res.removeHeader('X-Powered-By');
|
|
39
|
+
next();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Parameter validation middleware
|
|
45
|
+
validateQueryParams(allowedParams = {}) {
|
|
46
|
+
return (req, res, next) => {
|
|
47
|
+
try {
|
|
48
|
+
const normalized = {};
|
|
49
|
+
|
|
50
|
+
// Check for parameter pollution (arrays) and validate
|
|
51
|
+
for (const [key, value] of Object.entries(req.query)) {
|
|
52
|
+
if (Array.isArray(value)) {
|
|
53
|
+
return res.status(400).json({
|
|
54
|
+
error: 'Parameter pollution detected',
|
|
55
|
+
parameter: key
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (allowedParams[key]) {
|
|
60
|
+
const config = allowedParams[key];
|
|
61
|
+
|
|
62
|
+
if (value !== undefined) {
|
|
63
|
+
if (typeof value !== 'string') {
|
|
64
|
+
return res.status(400).json({
|
|
65
|
+
error: `Parameter ${key} must be a string`
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (value.length > (config.maxLength || 255)) {
|
|
70
|
+
return res.status(400).json({
|
|
71
|
+
error: `Parameter ${key} too long (max ${config.maxLength || 255})`
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (config.pattern && !config.pattern.test(value)) {
|
|
76
|
+
return res.status(400).json({
|
|
77
|
+
error: `Parameter ${key} has invalid format`
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
normalized[key] = value;
|
|
82
|
+
} else if (config.required) {
|
|
83
|
+
return res.status(400).json({
|
|
84
|
+
error: `Parameter ${key} is required`
|
|
85
|
+
});
|
|
86
|
+
} else {
|
|
87
|
+
normalized[key] = config.default || '';
|
|
88
|
+
}
|
|
89
|
+
} else if (value !== undefined) {
|
|
90
|
+
// Unknown parameter
|
|
91
|
+
return res.status(400).json({
|
|
92
|
+
error: `Unknown parameter: ${key}`
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Set default values for missing optional parameters
|
|
98
|
+
for (const [key, config] of Object.entries(allowedParams)) {
|
|
99
|
+
if (normalized[key] === undefined && !config.required) {
|
|
100
|
+
normalized[key] = config.default || '';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Clear and repopulate in-place (Express 5 makes req.query a read-only getter)
|
|
105
|
+
for (const key of Object.keys(req.query)) delete req.query[key];
|
|
106
|
+
Object.assign(req.query, normalized);
|
|
107
|
+
next();
|
|
108
|
+
} catch (error) {
|
|
109
|
+
vclLog.error('Parameter validation error:', error);
|
|
110
|
+
res.status(500).json({ error: 'Parameter validation failed' });
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Enhanced HTML escaping
|
|
116
|
+
escapeHtml(str) {
|
|
117
|
+
if (!str || typeof str !== 'string') return '';
|
|
118
|
+
|
|
119
|
+
const escapeMap = {
|
|
120
|
+
'&': '&',
|
|
121
|
+
'<': '<',
|
|
122
|
+
'>': '>',
|
|
123
|
+
'"': '"',
|
|
124
|
+
"'": ''',
|
|
125
|
+
'/': '/',
|
|
126
|
+
'`': '`',
|
|
127
|
+
'=': '='
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return str.replace(/[&<>"'`=/]/g, (match) => escapeMap[match]);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// VCL expression validation
|
|
134
|
+
validateVCLInput(vcl) {
|
|
135
|
+
if (!vcl || typeof vcl !== 'string') {
|
|
136
|
+
throw new Error('VCL expression must be a non-empty string');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Length validation
|
|
140
|
+
if (vcl.length > 10000) {
|
|
141
|
+
throw new Error('VCL expression too long (max 10000 characters)');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Basic character validation - allow VCL-specific characters
|
|
145
|
+
// VCL expressions can contain: letters, numbers, dots, hyphens, underscores,
|
|
146
|
+
// colons, slashes, pipes, parentheses, square brackets, equals, commas, spaces
|
|
147
|
+
const allowedCharsPattern = /^[a-zA-Z0-9.\-_:/|()[\]=, \t\r\n]*$/;
|
|
148
|
+
if (!allowedCharsPattern.test(vcl)) {
|
|
149
|
+
throw new Error('VCL expression contains invalid characters');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Check for potential injection patterns
|
|
153
|
+
const suspiciousPatterns = [
|
|
154
|
+
/<script/i,
|
|
155
|
+
/javascript:/i,
|
|
156
|
+
/on\w+\s*=/i,
|
|
157
|
+
/expression\s*\(/i,
|
|
158
|
+
/eval\s*\(/i,
|
|
159
|
+
/document\./i,
|
|
160
|
+
/window\./i
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
for (const pattern of suspiciousPatterns) {
|
|
164
|
+
if (pattern.test(vcl)) {
|
|
165
|
+
throw new Error('VCL expression contains potentially malicious content');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return vcl;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async initialize(config) {
|
|
173
|
+
this.config = config;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
setupRoutes() {
|
|
177
|
+
// Parameter validation config for VCL endpoint
|
|
178
|
+
const vclParams = {
|
|
179
|
+
vcl: {
|
|
180
|
+
required: true,
|
|
181
|
+
maxLength: 10000
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// VCL parsing endpoint
|
|
186
|
+
this.router.get('/', this.validateQueryParams(vclParams), (req, res) => {
|
|
187
|
+
const start = Date.now();
|
|
188
|
+
try {
|
|
189
|
+
var {vcl} = req.query;
|
|
190
|
+
|
|
191
|
+
// Validation
|
|
192
|
+
if (!vcl) {
|
|
193
|
+
return res.status(400).json({
|
|
194
|
+
error: 'VCL expression is required as query parameter: ?vcl=<expression>'
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (vcl.startsWith('http://fhir.org/VCL/')) {
|
|
199
|
+
vcl = vcl.substring(20);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
// Validate the VCL expression first
|
|
204
|
+
if (!validateVCLExpression(vcl)) {
|
|
205
|
+
return res.status(400).json({
|
|
206
|
+
error: 'Invalid VCL expression syntax'
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Parse the VCL expression and generate ValueSet with ID
|
|
211
|
+
const valueSet = parseVCLAndSetId(vcl);
|
|
212
|
+
|
|
213
|
+
// Return the ValueSet as JSON
|
|
214
|
+
res.json(valueSet);
|
|
215
|
+
|
|
216
|
+
} catch (error) {
|
|
217
|
+
vclLog.error('VCL parsing error:' + error);
|
|
218
|
+
|
|
219
|
+
if (error instanceof VCLParseException) {
|
|
220
|
+
return res.status(400).json({
|
|
221
|
+
error: 'VCL parsing error',
|
|
222
|
+
message: error.message,
|
|
223
|
+
position: error.position >= 0 ? error.position : undefined
|
|
224
|
+
});
|
|
225
|
+
} else {
|
|
226
|
+
return res.status(500).json({
|
|
227
|
+
error: 'Internal server error while parsing VCL',
|
|
228
|
+
message: error.message
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} finally {
|
|
233
|
+
this.stats.countRequest('vcl', Date.now() - start);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async shutdown() {
|
|
239
|
+
// VCL module doesn't have any resources to clean up
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
getStatus() {
|
|
243
|
+
return {
|
|
244
|
+
enabled: true
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
countRequest(name, tat) {
|
|
249
|
+
this.stats.countRequest(name, tat);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
module.exports = VCLModule;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// npm install -g node-windows
|
|
2
|
+
// npm link node-windows
|
|
3
|
+
|
|
4
|
+
var Service = require('node-windows').Service;
|
|
5
|
+
|
|
6
|
+
// Create a new service object
|
|
7
|
+
var svc = new Service({
|
|
8
|
+
name:'FHIRServer-Node',
|
|
9
|
+
description: 'FHIRsmith',
|
|
10
|
+
script: "C:\\FHIRsmith\\server.js"
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// Listen for the "install" event, which indicates the
|
|
14
|
+
// process is available as a service.
|
|
15
|
+
svc.on('install',function(){
|
|
16
|
+
svc.start();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
svc.install();
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
|
|
3
|
+
<html xml:lang="en" lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<title>FHIRsmith: [%title%]</title>
|
|
6
|
+
|
|
7
|
+
<meta charset="utf-8"/>
|
|
8
|
+
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
|
9
|
+
<meta content="http://hl7.org/fhir" name="author"/>
|
|
10
|
+
<meta charset="utf-8" http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
11
|
+
|
|
12
|
+
<link rel="stylesheet" href="/fhir.css"/>
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
<!-- Bootstrap core CSS -->
|
|
16
|
+
<link rel="stylesheet" href="/assets/css/bootstrap.css"/>
|
|
17
|
+
<link rel="stylesheet" href="/assets/css/bootstrap-fhir.css"/>
|
|
18
|
+
|
|
19
|
+
<!-- Project extras -->
|
|
20
|
+
<link rel="stylesheet" href="/assets/css/project.css"/>
|
|
21
|
+
<link rel="stylesheet" href="/assets/css/pygments-manni.css"/>
|
|
22
|
+
|
|
23
|
+
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
|
24
|
+
<!-- [if lt IE 9]>
|
|
25
|
+
<script src="/assets/js/html5shiv.js"></script>
|
|
26
|
+
<script src="/assets/js/respond.min.js"></script>
|
|
27
|
+
<![endif] -->
|
|
28
|
+
|
|
29
|
+
<!-- Favicons -->
|
|
30
|
+
<link sizes="144x144" rel="apple-touch-icon-precomposed" href="/assets/ico/apple-touch-icon-144-precomposed.png"/>
|
|
31
|
+
<link sizes="114x114" rel="apple-touch-icon-precomposed" href="/assets/ico/apple-touch-icon-114-precomposed.png"/>
|
|
32
|
+
<link sizes="72x72" rel="apple-touch-icon-precomposed" href="/assets/ico/apple-touch-icon-72-precomposed.png"/>
|
|
33
|
+
<link rel="apple-touch-icon-precomposed" href="/assets/ico/apple-touch-icon-57-precomposed.png"/>
|
|
34
|
+
<link rel="shortcut icon" href="/assets/ico/favicon.png"/>
|
|
35
|
+
<script type="text/javascript" src="/assets/js/json2.js"></script>
|
|
36
|
+
<script type="text/javascript" src="/assets/js/statuspage.js"></script>
|
|
37
|
+
<script type="text/javascript" src="/assets/js/jquery.min.js"></script>
|
|
38
|
+
<script type="text/javascript" src="/assets/js/jquery-ui.min.js"></script>
|
|
39
|
+
<link rel="stylesheet" href="/assets/css/jquery.ui.all.css">
|
|
40
|
+
<script type="text/javascript" src="/assets/js/jquery.ui.core.js"></script>
|
|
41
|
+
<script type="text/javascript" src="/assets/js/jquery.ui.widget.js"></script>
|
|
42
|
+
<script type="text/javascript" src="/assets/js/jquery.ui.mouse.js"></script>
|
|
43
|
+
<script type="text/javascript" src="/assets/js/jquery.ui.resizable.js"></script>
|
|
44
|
+
<script type="text/javascript" src="/assets/js/jquery.ui.draggable.js"></script>
|
|
45
|
+
<script type="text/javascript" src="/assets/js/jtip.js"></script>
|
|
46
|
+
<script type="text/javascript" src="/assets/js/jcookie.js"></script>
|
|
47
|
+
<script type="text/javascript" src="/assets/js/fhir-gw.js"></script>
|
|
48
|
+
</head>
|
|
49
|
+
|
|
50
|
+
<body>
|
|
51
|
+
|
|
52
|
+
<div id="segment-navbar" class="segment"> <!-- segment-breadcrumb -->
|
|
53
|
+
<div id="stripe"> </div>
|
|
54
|
+
<div class="container"> <!-- container -->
|
|
55
|
+
<div style="background-color: #ad1f2f; padding: 6px; color: white;"> <!-- container -->
|
|
56
|
+
<a href="http://www.hl7.org/fhir" style="color: gold" title="Fast Healthcare Interoperability Resources - Home Page"><img border="0" src="/icon-fhir-16.png" style="vertical-align: text-bottom"/> <b>FHIR</b></a> © HL7.org |
|
|
57
|
+
<a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] |
|
|
58
|
+
<a href="/" style="color: gold"> Server Home</a> |
|
|
59
|
+
<a href="/xig" style="color: gold">XIG Home</a> |
|
|
60
|
+
<a href="/xig/stats" style="color: gold">XIG Stats</a> |
|
|
61
|
+
</div> <!-- /container -->
|
|
62
|
+
</div> <!-- /container -->
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<!-- /segment-breadcrumb -->
|
|
66
|
+
|
|
67
|
+
<div id="segment-content" class="segment"> <!-- segment-content -->
|
|
68
|
+
<div class="container"> <!-- container -->
|
|
69
|
+
<div class="row">
|
|
70
|
+
<div class="inner-wrapper">
|
|
71
|
+
<div class="col-9">
|
|
72
|
+
|
|
73
|
+
<h2><img border="0" src="../FHIRsmith32.png" style="vertical-align: text-bottom"/> FHIR IG analytics</h2>
|
|
74
|
+
|
|
75
|
+
[%content%]
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
</div> <!-- /inner-wrapper -->
|
|
82
|
+
</div> <!-- /row -->
|
|
83
|
+
</div> <!-- /container -->
|
|
84
|
+
</div> <!-- /segment-content -->
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
<div id="segment-footer" class="segment"> <!-- segment-footer -->
|
|
88
|
+
<div class="container"> <!-- container -->
|
|
89
|
+
<div class="inner-wrapper">
|
|
90
|
+
<p>
|
|
91
|
+
<a href="http://www.hl7.org/fhir" style="color: gold" title="Fast Healthcare Interoperability Resources - Home Page"><img border="0" src="/icon-fhir-16.png" style="vertical-align: text-bottom"/> <b>FHIR</b></a> © HL7.org 2011+. |
|
|
92
|
+
<a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] © HealthIntersections.com.au 2023+ |
|
|
93
|
+
XIG built as of [%download-date%] | [%total-resources%] resources in [%total-packages%] packages | ([%ms%] ms)
|
|
94
|
+
</p>
|
|
95
|
+
</div> <!-- /inner-wrapper -->
|
|
96
|
+
</div> <!-- /container -->
|
|
97
|
+
</div> <!-- /segment-footer -->
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
<div id="segment-post-footer" class="segment hidden"> <!-- segment-post-footer -->
|
|
101
|
+
<div class="container"> <!-- container -->
|
|
102
|
+
</div> <!-- /container -->
|
|
103
|
+
</div> <!-- /segment-post-footer -->
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
<!-- JS and analytics only. -->
|
|
110
|
+
<!-- Bootstrap core JavaScript
|
|
111
|
+
================================================== -->
|
|
112
|
+
<!-- Placed at the end of the document so the pages load faster -->
|
|
113
|
+
<!-- <script src="/assets/js/jquery.js"/> -->
|
|
114
|
+
<script src="/assets/js/bootstrap.min.js"/>
|
|
115
|
+
<script src="/assets/js/respond.min.js"/>
|
|
116
|
+
|
|
117
|
+
<script src="/assets/js/fhir.js"/>
|
|
118
|
+
|
|
119
|
+
<!-- Analytics Below
|
|
120
|
+
================================================== -->
|
|
121
|
+
|
|
122
|
+
</body>
|
|
123
|
+
|
|
124
|
+
</html>
|