fhirsmith 0.18.2 → 1.0.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/ACCESSIBILITY.md +119 -0
- package/CHANGELOG.md +149 -0
- package/CONFIGURATION.md +305 -0
- package/LICENSE +29 -0
- package/README.md +29 -122
- package/cluster.js +1220 -0
- package/cluster.md +707 -0
- package/config-template.json +77 -8
- package/extension-tracker/extension-tracker-template.html +5 -8
- package/extension-tracker/extension-tracker.js +0 -2
- package/folder/folder.js +7 -6
- package/ips/analysis.js +560 -0
- package/ips/ips-template.html +5 -8
- package/ips/ips.js +132 -59
- package/ips/nationality.js +120 -0
- package/ips/pipeline.js +74 -21
- package/ips/presenter.js +1 -1
- package/ips/readme.md +132 -25
- package/ips/render.js +466 -77
- package/ips/store.js +79 -22
- package/ips/structure.js +247 -0
- package/ips/terminology.js +1 -1
- package/library/body-limit.js +22 -0
- package/library/cache-generation.js +15 -0
- package/library/cgroup-memory.js +133 -1
- package/library/cluster-counts.js +121 -0
- package/library/cluster-events.js +153 -0
- package/library/cluster-metrics.js +193 -0
- package/library/cluster-status.js +468 -0
- package/library/config-reader.js +96 -0
- package/library/daily-report.js +100 -2
- package/library/html-server.js +27 -1
- package/library/i18nsupport.js +23 -1
- package/library/keep-alive.js +18 -0
- package/library/languages.js +17 -3
- package/library/logger.js +31 -0
- package/library/memory-guard.js +428 -0
- package/library/native-memory.js +52 -0
- package/library/npm-audit.js +51 -25
- package/library/openapi-doc.js +7 -5
- package/library/package-manager.js +8 -0
- package/library/role.js +197 -0
- package/library/server-credentials.js +169 -0
- package/library/sqlite-utilities.js +59 -0
- package/library/ssrf-guard.js +100 -0
- package/library/static-response-stats.js +16 -0
- package/library/version-utilities.js +50 -0
- package/library/worker-count.js +192 -0
- package/nginx.md +30 -11
- package/npmprojector/indexer.js +18 -10
- package/package.json +11 -8
- package/packages/feed-check-page.js +117 -0
- package/packages/feed-check.js +279 -0
- package/packages/npm-check.js +57 -3
- package/packages/npm-signing.js +219 -0
- package/packages/openapi.yaml +207 -1
- package/packages/package-crawler.js +322 -41
- package/packages/packages-template.html +6 -8
- package/packages/packages.js +604 -57
- package/packages/readme.md +113 -1
- package/publisher/publisher-template.html +2 -5
- package/publisher/publisher.js +121 -110
- package/publisher/readme.md +75 -0
- package/registry/crawler.js +84 -108
- package/registry/documentation/configuration.md +34 -0
- package/registry/registry-template.html +5 -8
- package/registry/registry.js +5 -4
- package/root-bare-template.html +7 -4
- package/root-template.html +5 -8
- package/server.js +398 -198
- package/shl/shl.js +38 -37
- package/static/a11y/a11y-check.js +832 -0
- package/static/a11y/axe.min.js +12 -0
- package/static/assets/css/bootstrap-fhir.css +15 -15
- package/static/assets/images/flags/au.svg +18 -0
- package/static/assets/images/flags/unknown.svg +11 -0
- package/static/assets/images/flags/us.svg +63 -0
- package/static/assets/images/icon_audit.png +0 -0
- package/static/assets/images/icon_clinical.png +0 -0
- package/static/assets/images/icon_document.png +0 -0
- package/static/assets/images/icon_external.png +0 -0
- package/static/assets/images/icon_medication.png +0 -0
- package/static/assets/images/icon_organization.png +0 -0
- package/static/assets/images/icon_other.png +0 -0
- package/static/assets/images/icon_person.png +0 -0
- package/static/assets/images/icon_section.png +0 -0
- package/stats-db.js +45 -0
- package/stats.js +197 -10
- package/testing/testing-template.html +5 -8
- package/token/nginx_passport_setup.md +1 -1
- package/token/security_guide.md +1 -1
- package/token/token-template.html +2 -5
- package/token/token.js +40 -36
- package/translations/Messages.properties +19 -0
- package/tx/README.md +154 -4
- package/tx/closure/closure-store.js +126 -3
- package/tx/cm/cm-database.js +69 -57
- package/tx/cm/cm-package.js +29 -1
- package/tx/cs/cs-api.js +284 -19
- package/tx/cs/cs-api.md +41 -4
- package/tx/cs/cs-areacode.js +1 -1
- package/tx/cs/cs-country.js +17 -5
- package/tx/cs/cs-cpt.js +33 -16
- package/tx/cs/cs-cs.js +148 -14
- package/tx/cs/cs-currency.js +1 -1
- package/tx/cs/cs-icd11.js +21 -13
- package/tx/cs/cs-icf.js +22 -3
- package/tx/cs/cs-lang.js +2 -2
- package/tx/cs/cs-loinc.js +185 -66
- package/tx/cs/cs-mimetypes.js +12 -2
- package/tx/cs/cs-ndc.js +40 -25
- package/tx/cs/cs-omop.js +54 -29
- package/tx/cs/cs-rxnorm.js +300 -196
- package/tx/cs/cs-snomed.js +608 -64
- package/tx/cs/cs-ucum.js +14 -4
- package/tx/cs/cs-unii.js +18 -14
- package/tx/cs/cs-virtual.js +210 -0
- package/tx/ecosystem-resolver.js +413 -0
- package/tx/html/cluster-dash-metrics.liquid +26 -0
- package/tx/html/cluster-home-metrics.liquid +31 -0
- package/tx/html/cluster-metrics-script.liquid +251 -0
- package/tx/html/codesystem-operations.liquid +3 -3
- package/tx/html/ecl-panel.liquid +1 -1
- package/tx/html/external-metrics.liquid +17 -0
- package/tx/html/operations-form.liquid +17 -17
- package/tx/html/search-form.liquid +11 -11
- package/tx/html/status-line.liquid +58 -0
- package/tx/html/status-panel.liquid +140 -0
- package/tx/html/status-tasks.liquid +25 -0
- package/tx/html/tx-template.html +2 -5
- package/tx/importers/atc-to-fhir.js +17 -16
- package/tx/importers/export-icd11-codesystem.js +3 -2
- package/tx/importers/import-icd11.js +4 -3
- package/tx/importers/import-loinc.module.js +118 -56
- package/tx/importers/import-ndc.module.js +56 -44
- package/tx/importers/import-rxnorm.module.js +118 -79
- package/tx/importers/import-sct.module.js +57 -58
- package/tx/importers/import-unii.module.js +37 -36
- package/tx/importers/subset-loinc.module.js +49 -48
- package/tx/importers/subset-rxnorm.module.js +29 -28
- package/tx/importers/terminal.js +18 -0
- package/tx/importers/tx-import-base.js +13 -12
- package/tx/importers/tx-import-settings.js +5 -4
- package/tx/importers/tx-import.js +53 -52
- package/tx/library/canonical-resource.js +49 -0
- package/tx/library/codesystem.js +94 -5
- package/tx/library/designations.js +45 -2
- package/tx/library/extensions.js +13 -7
- package/tx/library/implicit-valuesets.js +66 -0
- package/tx/library/renderer.js +77 -21
- package/tx/library/sqlite-utilities.js +2 -0
- package/tx/library/ucum-parsers.js +11 -1
- package/tx/library/wait-for-cache.js +43 -0
- package/tx/library.js +321 -22
- package/tx/openapi-operations.js +6 -4
- package/tx/operation-context.js +460 -99
- package/tx/params.js +25 -0
- package/tx/problems.js +3 -5
- package/tx/provider.js +278 -42
- package/tx/resource-cache-sqlite.js +1050 -0
- package/tx/sct/ecl.js +47 -6
- package/tx/sct/editions.js +39 -0
- package/tx/sct/expressions.js +10 -1
- package/tx/sct/load-config.js +107 -0
- package/tx/sct/mmap.js +109 -0
- package/tx/sct/structures.js +166 -13
- package/tx/sct/text-index.js +5 -1
- package/tx/syndication/syndication-feed.js +2 -2
- package/tx/tx-html.js +44 -8
- package/tx/tx.fhir.org.yml +8 -8
- package/tx/tx.js +282 -80
- package/tx/usage-tracker.js +39 -11
- package/tx/vs/vs-api.js +19 -0
- package/tx/vs/vs-database.js +386 -62
- package/tx/vs/vs-package.js +27 -4
- package/tx/vs/vs-vsac.js +648 -100
- package/tx/workers/batch-validate.js +37 -10
- package/tx/workers/batch.js +6 -1
- package/tx/workers/cache-control.js +15 -4
- package/tx/workers/closure.js +156 -13
- package/tx/workers/compare.js +8 -5
- package/tx/workers/expand.js +1173 -289
- package/tx/workers/metadata.js +35 -0
- package/tx/workers/search.js +53 -1
- package/tx/workers/supplement-filters.js +145 -0
- package/tx/workers/translate.js +169 -4
- package/tx/workers/validate.js +223 -119
- package/tx/workers/worker.js +123 -31
- package/tx/xversion/xv-valueset.js +7 -4
- package/utilities/submit-test-report.js +3 -1
- package/utilities/tx-stress-test.js +482 -0
- package/vcl/readme.md +37 -0
- package/vcl/vcl-parser.js +15 -0
- package/xig/readme.md +52 -0
- package/xig/xig-template.html +5 -8
- package/xig/xig.js +238 -422
- package/changelog-template.md +0 -22
- package/registry/test-runner.js +0 -237
- package/release.sh +0 -80
- package/test-scripts/repro-re2-wasm-leak.js +0 -34
- package/tsconfig.eslint.json +0 -9
- package/tx/html/dash-metrics.liquid +0 -147
- package/tx/html/home-metrics.liquid +0 -225
package/changelog-template.md
DELETED
package/registry/test-runner.js
DELETED
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
// test-runner.js
|
|
2
|
-
// Quick test runner to verify the fixes
|
|
3
|
-
|
|
4
|
-
const {
|
|
5
|
-
ServerRegistries,
|
|
6
|
-
ServerRegistry,
|
|
7
|
-
ServerInformation,
|
|
8
|
-
ServerVersionInformation
|
|
9
|
-
} = require('./registry-model');
|
|
10
|
-
const RegistryCrawler = require('./registry/crawler');
|
|
11
|
-
const RegistryAPI = require('./registry-api');
|
|
12
|
-
|
|
13
|
-
// Create sample test data
|
|
14
|
-
function createSampleData() {
|
|
15
|
-
const data = new ServerRegistries();
|
|
16
|
-
data.address = 'https://registry.example.org';
|
|
17
|
-
data.lastRun = new Date('2024-01-15T10:00:00Z');
|
|
18
|
-
data.outcome = 'Crawled 2 registries successfully, 0 errors';
|
|
19
|
-
data.doco = 'Test registry for unit tests';
|
|
20
|
-
|
|
21
|
-
// Registry 1: Main Registry
|
|
22
|
-
const reg1 = new ServerRegistry();
|
|
23
|
-
reg1.code = 'main';
|
|
24
|
-
reg1.name = 'Main Terminology Registry';
|
|
25
|
-
reg1.address = 'https://main.registry.org';
|
|
26
|
-
reg1.authority = 'HL7 International';
|
|
27
|
-
|
|
28
|
-
// Server 1.1: TX Server
|
|
29
|
-
const server11 = new ServerInformation();
|
|
30
|
-
server11.code = 'tx1';
|
|
31
|
-
server11.name = 'TX Terminology Server';
|
|
32
|
-
server11.address = 'https://tx.fhir.org';
|
|
33
|
-
server11.accessInfo = 'Public FHIR terminology server';
|
|
34
|
-
server11.authCSList = ['http://loinc.org*', 'http://snomed.info/sct*'];
|
|
35
|
-
server11.authVSList = ['http://hl7.org/fhir/ValueSet/loinc*'];
|
|
36
|
-
server11.usageList = ['production', 'public'];
|
|
37
|
-
|
|
38
|
-
// Version 4.0.1 for TX Server
|
|
39
|
-
const version111 = new ServerVersionInformation();
|
|
40
|
-
version111.version = '4.0.1';
|
|
41
|
-
version111.address = 'https://tx.fhir.org/r4';
|
|
42
|
-
version111.security = 'open';
|
|
43
|
-
version111.lastSuccess = new Date('2024-01-15T09:55:00Z');
|
|
44
|
-
version111.lastTat = '250ms';
|
|
45
|
-
version111.codeSystems = [
|
|
46
|
-
'http://loinc.org',
|
|
47
|
-
'http://snomed.info/sct',
|
|
48
|
-
'http://hl7.org/fhir/sid/icd-10',
|
|
49
|
-
'http://www.nlm.nih.gov/research/umls/rxnorm'
|
|
50
|
-
].sort();
|
|
51
|
-
version111.valueSets = [
|
|
52
|
-
'http://hl7.org/fhir/ValueSet/observation-codes',
|
|
53
|
-
'http://hl7.org/fhir/ValueSet/condition-code',
|
|
54
|
-
'http://hl7.org/fhir/ValueSet/loinc-diagnostic-report-codes'
|
|
55
|
-
].sort();
|
|
56
|
-
server11.versions.push(version111);
|
|
57
|
-
|
|
58
|
-
// Version 5.0.0 for TX Server (doesn't have loinc-diagnostic-report-codes)
|
|
59
|
-
const version112 = new ServerVersionInformation();
|
|
60
|
-
version112.version = '5.0.0';
|
|
61
|
-
version112.address = 'https://tx.fhir.org/r5';
|
|
62
|
-
version112.security = 'open';
|
|
63
|
-
version112.lastSuccess = new Date('2024-01-15T09:56:00Z');
|
|
64
|
-
version112.lastTat = '180ms';
|
|
65
|
-
version112.codeSystems = [
|
|
66
|
-
'http://loinc.org',
|
|
67
|
-
'http://snomed.info/sct',
|
|
68
|
-
'http://hl7.org/fhir/sid/icd-11'
|
|
69
|
-
].sort();
|
|
70
|
-
version112.valueSets = [
|
|
71
|
-
'http://hl7.org/fhir/ValueSet/observation-codes'
|
|
72
|
-
].sort();
|
|
73
|
-
server11.versions.push(version112);
|
|
74
|
-
|
|
75
|
-
// Server 1.2: Ontoserver
|
|
76
|
-
const server12 = new ServerInformation();
|
|
77
|
-
server12.code = 'onto';
|
|
78
|
-
server12.name = 'Ontoserver';
|
|
79
|
-
server12.address = 'https://ontoserver.example.org';
|
|
80
|
-
server12.accessInfo = 'Enterprise terminology server';
|
|
81
|
-
server12.authCSList = ['http://snomed.info/sct*'];
|
|
82
|
-
server12.authVSList = [];
|
|
83
|
-
server12.usageList = ['production'];
|
|
84
|
-
|
|
85
|
-
const version121 = new ServerVersionInformation();
|
|
86
|
-
version121.version = '6.4.0';
|
|
87
|
-
version121.address = 'https://ontoserver.example.org/fhir';
|
|
88
|
-
version121.security = 'oauth';
|
|
89
|
-
version121.lastSuccess = new Date('2024-01-15T09:50:00Z');
|
|
90
|
-
version121.lastTat = '180ms';
|
|
91
|
-
version121.codeSystems = [
|
|
92
|
-
'http://snomed.info/sct',
|
|
93
|
-
'http://snomed.info/sct/32506021000036107',
|
|
94
|
-
'http://loinc.org'
|
|
95
|
-
].sort();
|
|
96
|
-
version121.valueSets = [
|
|
97
|
-
'http://snomed.info/sct?fhir_vs=ecl/<404684003',
|
|
98
|
-
'http://snomed.info/sct?fhir_vs=ecl/<373873005'
|
|
99
|
-
].sort();
|
|
100
|
-
server12.versions.push(version121);
|
|
101
|
-
|
|
102
|
-
reg1.servers.push(server11);
|
|
103
|
-
reg1.servers.push(server12);
|
|
104
|
-
|
|
105
|
-
// Registry 2: Test Registry
|
|
106
|
-
const reg2 = new ServerRegistry();
|
|
107
|
-
reg2.code = 'test';
|
|
108
|
-
reg2.name = 'Test Terminology Registry';
|
|
109
|
-
reg2.address = 'https://test.registry.org';
|
|
110
|
-
reg2.authority = 'Testing Authority';
|
|
111
|
-
|
|
112
|
-
// Server 2.1: Test Server with error
|
|
113
|
-
const server21 = new ServerInformation();
|
|
114
|
-
server21.code = 'test-server';
|
|
115
|
-
server21.name = 'Test Server';
|
|
116
|
-
server21.address = 'https://test.server.org';
|
|
117
|
-
server21.accessInfo = 'Test server (currently down)';
|
|
118
|
-
|
|
119
|
-
const version211 = new ServerVersionInformation();
|
|
120
|
-
version211.version = '1.0.0';
|
|
121
|
-
version211.address = 'https://test.server.org/fhir';
|
|
122
|
-
version211.error = 'Connection timeout';
|
|
123
|
-
server21.versions.push(version211);
|
|
124
|
-
|
|
125
|
-
// Server 2.2: Local Dev Server
|
|
126
|
-
const server22 = new ServerInformation();
|
|
127
|
-
server22.code = 'local';
|
|
128
|
-
server22.name = 'Local Development Server';
|
|
129
|
-
server22.address = 'http://localhost:8080';
|
|
130
|
-
server22.accessInfo = 'Local development instance';
|
|
131
|
-
server22.authCSList = ['http://example.org/codesystem/*'];
|
|
132
|
-
server22.authVSList = ['http://example.org/valueset/*'];
|
|
133
|
-
|
|
134
|
-
const version221 = new ServerVersionInformation();
|
|
135
|
-
version221.version = '5.0.0';
|
|
136
|
-
version221.address = 'http://localhost:8080/fhir';
|
|
137
|
-
version221.security = 'open';
|
|
138
|
-
version221.lastSuccess = new Date('2024-01-15T08:00:00Z');
|
|
139
|
-
version221.lastTat = '50ms';
|
|
140
|
-
version221.codeSystems = [
|
|
141
|
-
'http://example.org/codesystem/test1',
|
|
142
|
-
'http://example.org/codesystem/test2',
|
|
143
|
-
'http://hl7.org/fhir/sid/icd-10'
|
|
144
|
-
].sort();
|
|
145
|
-
version221.valueSets = [
|
|
146
|
-
'http://example.org/valueset/test1',
|
|
147
|
-
'http://example.org/valueset/test2'
|
|
148
|
-
].sort();
|
|
149
|
-
server22.versions.push(version221);
|
|
150
|
-
|
|
151
|
-
reg2.servers.push(server21);
|
|
152
|
-
reg2.servers.push(server22);
|
|
153
|
-
|
|
154
|
-
data.registries.push(reg1);
|
|
155
|
-
data.registries.push(reg2);
|
|
156
|
-
|
|
157
|
-
return data;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Run specific tests
|
|
161
|
-
function runTests() {
|
|
162
|
-
const crawler = new RegistryCrawler();
|
|
163
|
-
crawler.loadData(createSampleData().toJSON());
|
|
164
|
-
const api = new RegistryAPI(crawler);
|
|
165
|
-
|
|
166
|
-
console.log('\nRunning problematic tests:\n');
|
|
167
|
-
|
|
168
|
-
// Test 1: should return all servers when no filter specified
|
|
169
|
-
console.log('Test 1: should return all servers when no filter specified');
|
|
170
|
-
const rows1 = api.buildRowsForCodeSystem({});
|
|
171
|
-
console.log(` Expected: 4 working versions`);
|
|
172
|
-
console.log(` Received: ${rows1.length} versions`);
|
|
173
|
-
console.log(` Server codes: ${rows1.map(r => `${r.serverCode}(${r.version})`).join(', ')}`);
|
|
174
|
-
console.log(` Test ${rows1.length === 4 ? '✓ PASSED' : '✗ FAILED'}\n`);
|
|
175
|
-
|
|
176
|
-
// Test 2: should handle wildcard value set matching
|
|
177
|
-
console.log('Test 2: should handle wildcard value set matching');
|
|
178
|
-
const rows2 = api.buildRowsForValueSet({
|
|
179
|
-
valueSet: 'http://hl7.org/fhir/ValueSet/loinc-diagnostic-report-codes'
|
|
180
|
-
});
|
|
181
|
-
console.log(` Query: 'http://hl7.org/fhir/ValueSet/loinc-diagnostic-report-codes'`);
|
|
182
|
-
console.log(` TX server is authoritative for: 'http://hl7.org/fhir/ValueSet/loinc*'`);
|
|
183
|
-
console.log(` Version 4.0.1 HAS this value set`);
|
|
184
|
-
console.log(` Version 5.0.0 does NOT have this value set`);
|
|
185
|
-
console.log(` Expected: 1 version (4.0.1 which has the value set) OR 2 versions (both authoritative)?`);
|
|
186
|
-
console.log(` Received: ${rows2.length} version(s)`);
|
|
187
|
-
if (rows2.length > 0) {
|
|
188
|
-
console.log(` Versions: ${rows2.map(r => `${r.version} (auth=${r.authoritative})`).join(', ')}`);
|
|
189
|
-
}
|
|
190
|
-
console.log(` Test ${rows2.length === 1 && rows2[0].version === '4.0.1' ? '✓ PASSED (strict)' : rows2.length === 2 ? '✓ PASSED (lenient)' : '✗ FAILED'}\n`);
|
|
191
|
-
|
|
192
|
-
// Test 3: should rank servers without errors higher
|
|
193
|
-
console.log('Test 3: should not include servers with errors even if authoritative');
|
|
194
|
-
const data = crawler.getData();
|
|
195
|
-
const testServer = data.registries[1].servers[0];
|
|
196
|
-
testServer.authCSList = ['http://test.org/*'];
|
|
197
|
-
|
|
198
|
-
const rows3 = api.buildRowsForCodeSystem({
|
|
199
|
-
codeSystem: 'http://test.org/cs'
|
|
200
|
-
});
|
|
201
|
-
const hasErrorServer = rows3.some(r => r.serverCode === 'test-server');
|
|
202
|
-
console.log(` Expected: No test-server in results`);
|
|
203
|
-
console.log(` Received: ${hasErrorServer ? 'test-server found' : 'test-server not found'}`);
|
|
204
|
-
console.log(` Servers in result: ${rows3.map(r => r.serverCode).join(', ')}`);
|
|
205
|
-
console.log(` Test ${!hasErrorServer ? '✓ PASSED' : '✗ FAILED'}\n`);
|
|
206
|
-
|
|
207
|
-
// Run all the other tests to make sure we didn't break anything
|
|
208
|
-
console.log('Running additional validation tests:\n');
|
|
209
|
-
|
|
210
|
-
// Test: Find servers supporting LOINC
|
|
211
|
-
const loincRows = api.buildRowsForCodeSystem({
|
|
212
|
-
codeSystem: 'http://loinc.org'
|
|
213
|
-
});
|
|
214
|
-
console.log('Test: Find servers supporting LOINC');
|
|
215
|
-
console.log(` Expected: 3 servers (tx1 v4, tx1 v5, onto v6)`);
|
|
216
|
-
console.log(` Received: ${loincRows.length} servers`);
|
|
217
|
-
console.log(` Test ${loincRows.length === 3 ? '✓ PASSED' : '✗ FAILED'}\n`);
|
|
218
|
-
|
|
219
|
-
// Test: Filter by version
|
|
220
|
-
const versionRows = api.buildRowsForCodeSystem({
|
|
221
|
-
version: '4.0',
|
|
222
|
-
codeSystem: 'http://loinc.org'
|
|
223
|
-
});
|
|
224
|
-
console.log('Test: Filter by version 4.0');
|
|
225
|
-
console.log(` Expected: 1 server (version 4.0.1)`);
|
|
226
|
-
console.log(` Received: ${versionRows.length} server(s)`);
|
|
227
|
-
if (versionRows.length > 0) {
|
|
228
|
-
console.log(` Version: ${versionRows[0].version}`);
|
|
229
|
-
}
|
|
230
|
-
console.log(` Test ${versionRows.length === 1 && versionRows[0].version === '4.0.1' ? '✓ PASSED' : '✗ FAILED'}\n`);
|
|
231
|
-
|
|
232
|
-
console.log('================================');
|
|
233
|
-
console.log('Test run complete!');
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Run the tests
|
|
237
|
-
runTests();
|
package/release.sh
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# Release FHIRsmith: ./release.sh 0.17.0
|
|
4
|
-
#
|
|
5
|
-
# Checks that the release is ready, submits the tx test report to the /testing server, then
|
|
6
|
-
# tags the release and pushes the tag (which starts .github/workflows/release.yml).
|
|
7
|
-
# Stops at the first problem, before anything is tagged.
|
|
8
|
-
#
|
|
9
|
-
# The test report: run the tx tests first (npx jest tests/tx/test-cases.test.js). If the
|
|
10
|
-
# /testing server needs a token, set FHIRSMITH_TESTING_TOKEN.
|
|
11
|
-
|
|
12
|
-
set -euo pipefail
|
|
13
|
-
|
|
14
|
-
fail() {
|
|
15
|
-
echo "gr.sh: $*" >&2
|
|
16
|
-
exit 1
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
[ $# -eq 1 ] || fail "usage: ./gr.sh <version>, e.g. ./gr.sh 0.17.0"
|
|
20
|
-
VERSION="${1#v}"
|
|
21
|
-
TAG="v$VERSION"
|
|
22
|
-
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || fail "'$1' is not a release version (X.Y.Z)"
|
|
23
|
-
|
|
24
|
-
cd "$(dirname "$0")"
|
|
25
|
-
|
|
26
|
-
# --- git: on main, nothing uncommitted, and exactly what is on GitHub -------------------
|
|
27
|
-
[ "$(git rev-parse --abbrev-ref HEAD)" = "main" ] || fail "not on main"
|
|
28
|
-
[ -z "$(git status --porcelain --untracked-files=no)" ] || fail "there are uncommitted changes"
|
|
29
|
-
git fetch --quiet origin main --tags
|
|
30
|
-
[ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ] \
|
|
31
|
-
|| fail "main is not the same as origin/main - push (or pull) first, so the tag is on a commit GitHub has"
|
|
32
|
-
! git rev-parse -q --verify "refs/tags/$TAG" >/dev/null || fail "tag $TAG already exists"
|
|
33
|
-
|
|
34
|
-
# --- versions: what release.yml's verify-version job checks ----------------------------
|
|
35
|
-
check_version() {
|
|
36
|
-
local what="$1" found="$2"
|
|
37
|
-
[ "$found" = "$VERSION" ] || fail "$what is '$found', not $VERSION (npm version --no-git-tag-version $VERSION && npm install --package-lock-only)"
|
|
38
|
-
}
|
|
39
|
-
check_version "package.json version" "$(node -p "require('./package.json').version")"
|
|
40
|
-
check_version "package-lock.json version" "$(node -p "require('./package-lock.json').version")"
|
|
41
|
-
check_version 'package-lock.json packages[""]' "$(node -p "require('./package-lock.json').packages[''].version")"
|
|
42
|
-
|
|
43
|
-
# --- CHANGELOG: a dated section for this version, with the conformance statement in -----
|
|
44
|
-
HEADING=$(grep -E "^## \[v?${VERSION//./\\.}\]" CHANGELOG.md || true)
|
|
45
|
-
[ -n "$HEADING" ] || fail "CHANGELOG.md has no section for $VERSION"
|
|
46
|
-
[[ "$HEADING" =~ [0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] || fail "the CHANGELOG.md section for $VERSION has no date: $HEADING"
|
|
47
|
-
SECTION=$(sed -n "/^## \[v\{0,1\}${VERSION//./\\.}\]/,/^## \[/p" CHANGELOG.md | sed '$d')
|
|
48
|
-
! grep -qx '(paste)' <<<"$SECTION" || fail "the Tx Conformance Statement for $VERSION hasn't been pasted into CHANGELOG.md"
|
|
49
|
-
|
|
50
|
-
# --- the test report: this version, passed, and run on what is being released ----------
|
|
51
|
-
REPORT=test-cases-report.json
|
|
52
|
-
[ -f "$REPORT" ] || fail "no $REPORT - run the tx tests first (npx jest tests/tx/test-cases.test.js)"
|
|
53
|
-
# the last commit that changed what the tests run - not the notes, nor the version bump
|
|
54
|
-
CODE_COMMITTED=$(git log -1 --format=%cI -- . ':(exclude)*.md' ':(exclude)release.sh' ':(exclude)package.json' ':(exclude)package-lock.json')
|
|
55
|
-
node - "$REPORT" "$VERSION" "$CODE_COMMITTED" <<'NODE' || exit 1
|
|
56
|
-
const [file, version, committed] = process.argv.slice(2);
|
|
57
|
-
const report = JSON.parse(require('fs').readFileSync(file, 'utf8'));
|
|
58
|
-
const fhirsmith = (report.participant || []).find(p => p.uri === 'https://github.com/HealthIntersections/FHIRsmith');
|
|
59
|
-
const problems = [];
|
|
60
|
-
if (!fhirsmith || fhirsmith.version !== version) {
|
|
61
|
-
problems.push(`it is from FHIRsmith ${fhirsmith ? fhirsmith.version : '(unknown)'}, not ${version}`);
|
|
62
|
-
}
|
|
63
|
-
if (report.result !== 'pass') {
|
|
64
|
-
problems.push(`its result is '${report.result}', not 'pass'`);
|
|
65
|
-
}
|
|
66
|
-
if (!report.issued || new Date(report.issued) < new Date(committed)) {
|
|
67
|
-
problems.push(`it was run (${report.issued}) before the last change to the code (${committed})`);
|
|
68
|
-
}
|
|
69
|
-
if (problems.length > 0) {
|
|
70
|
-
console.error(`gr.sh: ${file} can't be submitted for ${version}: ${problems.join('; ')} - run the tx tests again`);
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
NODE
|
|
74
|
-
|
|
75
|
-
# --- submit the report, then tag ---------------------------------------------------------
|
|
76
|
-
node utilities/submit-test-report.js -file "$REPORT" || fail "the test report was not accepted, so $TAG has not been tagged"
|
|
77
|
-
|
|
78
|
-
git tag -a "$TAG" -m "FHIRsmith $VERSION"
|
|
79
|
-
git push origin "$TAG"
|
|
80
|
-
echo "Tagged and pushed $TAG - the release workflow is now running"
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// Historical reproducer for the re2-wasm WASM heap leak.
|
|
2
|
-
// regex-utilities.js now sits on top of re2js (a pure-JS RE2 port), so the
|
|
3
|
-
// underlying leak is gone. Kept as a stress test for the compile cache:
|
|
4
|
-
//
|
|
5
|
-
// node test-scripts/repro-re2-wasm-leak.js # same-pattern stress
|
|
6
|
-
// node test-scripts/repro-re2-wasm-leak.js --unique # unique-pattern stress
|
|
7
|
-
//
|
|
8
|
-
// Background (re2-wasm era): without the cache, same-pattern OOMed at ~2965
|
|
9
|
-
// iterations; with the cache, same-pattern ran indefinitely but unique-pattern
|
|
10
|
-
// still OOMed because every distinct pattern was a real compile and re2-wasm
|
|
11
|
-
// could not free its WASM heap. Under re2js both modes now run indefinitely
|
|
12
|
-
// (unique-pattern is bounded only by ordinary V8 heap growth from the cache).
|
|
13
|
-
|
|
14
|
-
const re = require('../library/regex-utilities');
|
|
15
|
-
|
|
16
|
-
const mode = process.argv.includes('--unique') ? 'unique' : 'same';
|
|
17
|
-
const basePattern =
|
|
18
|
-
'CYTO|HL7\\.CYTOGEN|HL7\\.GENETICS|^PATH(\\..*)?|^MOLPATH(\\..*)?|NR STATS|H&P\\.HX\\.LAB|CHALSKIN|LABORDERS';
|
|
19
|
-
|
|
20
|
-
console.log(`mode: ${mode}-pattern`);
|
|
21
|
-
|
|
22
|
-
let i = 0;
|
|
23
|
-
try {
|
|
24
|
-
for (;;) {
|
|
25
|
-
const pattern = mode === 'unique' ? basePattern + `|UNIQUE${i}` : basePattern;
|
|
26
|
-
re.compile(pattern);
|
|
27
|
-
i++;
|
|
28
|
-
if (i % 100 === 0) console.log(`iter ${i}`);
|
|
29
|
-
}
|
|
30
|
-
} catch (e) {
|
|
31
|
-
console.error(`OOMed at iteration ${i}: ${e.message}`);
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
|
package/tsconfig.eslint.json
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"allowJs": true, "checkJs": false, "noEmit": true,
|
|
4
|
-
"moduleResolution": "node", "target": "es2022", "module": "commonjs",
|
|
5
|
-
"strict": false, "skipLibCheck": true
|
|
6
|
-
},
|
|
7
|
-
"include": ["**/*.js"],
|
|
8
|
-
"exclude": ["node_modules", "static", "**/*.test.js", "tests", "coverage"]
|
|
9
|
-
}
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
<div style="display: flex; gap: 20px; margin-bottom: 20px;">
|
|
2
|
-
<div style="flex: 1;">
|
|
3
|
-
<h6>Memory Usage (Heap Used)</h6>
|
|
4
|
-
<canvas id="memoryChart" height="200"></canvas>
|
|
5
|
-
</div>
|
|
6
|
-
<div style="flex: 1;">
|
|
7
|
-
<h6>Turnaround Time</h6>
|
|
8
|
-
<canvas id="tatChart" height="200"></canvas>
|
|
9
|
-
</div>
|
|
10
|
-
<div style="flex: 1;">
|
|
11
|
-
<h6>Requests per Minute</h6>
|
|
12
|
-
<canvas id="requestChart" height="200"></canvas>
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
17
|
-
<script>
|
|
18
|
-
(function() {
|
|
19
|
-
const historyData = {{ historyJson }};
|
|
20
|
-
const startTime = {{ startTime }};
|
|
21
|
-
|
|
22
|
-
function formatTime(timestamp) {
|
|
23
|
-
const d = new Date(timestamp);
|
|
24
|
-
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function formatMB(bytes) {
|
|
28
|
-
return (bytes / 1024 / 1024).toFixed(1);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function formatDuration(ms) {
|
|
32
|
-
const hours = ms / 3600000;
|
|
33
|
-
if (hours < 1) {
|
|
34
|
-
return Math.round(ms / 60000) + 'm ago';
|
|
35
|
-
}
|
|
36
|
-
return hours.toFixed(1) + 'h ago';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const chartOptions = {
|
|
40
|
-
responsive: false,
|
|
41
|
-
maintainAspectRatio: false,
|
|
42
|
-
scales: {
|
|
43
|
-
x: {
|
|
44
|
-
ticks: {
|
|
45
|
-
maxTicksAuto: 6
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
y: {
|
|
49
|
-
beginAtZero: true
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
plugins: {
|
|
53
|
-
legend: {
|
|
54
|
-
display: false
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
// Memory chart
|
|
60
|
-
new Chart(document.getElementById('memoryChart'), {
|
|
61
|
-
type: 'line',
|
|
62
|
-
data: {
|
|
63
|
-
labels: historyData.map(d => formatTime(d.time)),
|
|
64
|
-
datasets: [{
|
|
65
|
-
data: historyData.map(d => parseFloat(formatMB(d.mem))),
|
|
66
|
-
borderColor: '#007bff',
|
|
67
|
-
backgroundColor: 'rgba(0, 123, 255, 0.1)',
|
|
68
|
-
fill: true,
|
|
69
|
-
tension: 0.3,
|
|
70
|
-
pointRadius: 2
|
|
71
|
-
}]
|
|
72
|
-
},
|
|
73
|
-
options: {
|
|
74
|
-
...chartOptions,
|
|
75
|
-
scales: {
|
|
76
|
-
...chartOptions.scales,
|
|
77
|
-
y: {
|
|
78
|
-
...chartOptions.scales.y,
|
|
79
|
-
title: {
|
|
80
|
-
display: true,
|
|
81
|
-
text: 'MB (𝚫 from start)'
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Tat chart
|
|
90
|
-
new Chart(document.getElementById('tatChart'), {
|
|
91
|
-
type: 'line',
|
|
92
|
-
data: {
|
|
93
|
-
labels: historyData.map(d => formatTime(d.time)),
|
|
94
|
-
datasets: [{
|
|
95
|
-
data: historyData.map(d => d.tat),
|
|
96
|
-
borderColor: '#7b7b7b',
|
|
97
|
-
backgroundColor: 'rgba(123, 123, 123, 0.1)',
|
|
98
|
-
fill: true,
|
|
99
|
-
tension: 0.3,
|
|
100
|
-
pointRadius: 2
|
|
101
|
-
}]
|
|
102
|
-
},
|
|
103
|
-
options: {
|
|
104
|
-
...chartOptions,
|
|
105
|
-
scales: {
|
|
106
|
-
...chartOptions.scales,
|
|
107
|
-
y: {
|
|
108
|
-
...chartOptions.scales.y,
|
|
109
|
-
title: {
|
|
110
|
-
display: true,
|
|
111
|
-
text: 'ms'
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Requests chart
|
|
119
|
-
new Chart(document.getElementById('requestChart'), {
|
|
120
|
-
type: 'line',
|
|
121
|
-
data: {
|
|
122
|
-
labels: historyData.map(d => formatTime(d.time)),
|
|
123
|
-
datasets: [{
|
|
124
|
-
data: historyData.map(d => d.rpm.toFixed(2)),
|
|
125
|
-
borderColor: '#28a745',
|
|
126
|
-
backgroundColor: 'rgba(40, 167, 69, 0.1)',
|
|
127
|
-
fill: true,
|
|
128
|
-
tension: 0.3,
|
|
129
|
-
pointRadius: 2
|
|
130
|
-
}]
|
|
131
|
-
},
|
|
132
|
-
options: {
|
|
133
|
-
...chartOptions,
|
|
134
|
-
scales: {
|
|
135
|
-
...chartOptions.scales,
|
|
136
|
-
y: {
|
|
137
|
-
...chartOptions.scales.y,
|
|
138
|
-
title: {
|
|
139
|
-
display: true,
|
|
140
|
-
text: 'req/min'
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
})();
|
|
147
|
-
</script>
|