fhirsmith 0.8.5 → 0.8.6
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 +24 -0
- package/README.md +52 -22
- package/extension-tracker/extension-tracker-template.html +3 -1
- package/library/html-server.js +7 -0
- package/library/logger.js +234 -194
- package/package.json +2 -1
- package/packages/packages-template.html +3 -1
- package/publisher/publisher-template.html +1 -0
- package/registry/registry-template.html +3 -1
- package/root-template.html +3 -2
- package/server.js +48 -12
- package/translations/Messages.properties +1 -1
- package/translations/rendering-phrases.properties +3 -1
- package/tx/cs/cs-api.js +4 -0
- package/tx/cs/cs-cs.js +5 -1
- package/tx/cs/cs-snomed.js +4 -0
- package/tx/html/tx-template.html +3 -2
- package/tx/library/codesystem.js +4 -0
- package/tx/library/renderer.js +20 -4
- package/tx/operation-context.js +74 -19
- package/tx/tx-html.js +5 -5
- package/tx/tx.js +1 -0
- package/tx/workers/expand.js +149 -112
- package/tx/workers/metadata.js +3 -2
- package/tx/workers/read.js +6 -3
- package/tx/workers/related.js +228 -87
- package/xig/xig-template.html +3 -1
- package/library/logger-telnet.js +0 -205
package/library/logger.js
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
|
-
const winston = require('winston');
|
|
2
|
-
require('winston-daily-rotate-file');
|
|
3
1
|
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
4
3
|
const folders = require('./folder-setup');
|
|
5
4
|
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Buffered, daily-rotating logger
|
|
7
|
+
// - Writes are batched and flushed every FLUSH_INTERVAL ms or FLUSH_SIZE lines
|
|
8
|
+
// - this is intended to be highly efficient
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const DEFAULTS = {
|
|
12
|
+
level: 'info', // error, warn, info, debug, verbose
|
|
13
|
+
console: true, // write to stdout/stderr
|
|
14
|
+
consoleErrors: false, // include error/warn on console (when running as service, these go to journal)
|
|
15
|
+
maxFiles: 14, // number of daily log files to keep
|
|
16
|
+
maxSize: 0, // max bytes per file (0 = unlimited)
|
|
17
|
+
flushInterval: 2000, // ms between flushes
|
|
18
|
+
flushSize: 200, // flush when buffer reaches this many lines
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const LEVELS = { error: 0, warn: 1, info: 2, debug: 3, verbose: 4 };
|
|
22
|
+
|
|
6
23
|
class Logger {
|
|
7
24
|
static _instance = null;
|
|
8
25
|
|
|
@@ -13,260 +30,278 @@ class Logger {
|
|
|
13
30
|
return Logger._instance;
|
|
14
31
|
}
|
|
15
32
|
|
|
33
|
+
// options = config.logging section from config.json (all fields optional)
|
|
34
|
+
//
|
|
35
|
+
// Example config.json:
|
|
36
|
+
// {
|
|
37
|
+
// "logging": {
|
|
38
|
+
// "level": "info",
|
|
39
|
+
// "console": false,
|
|
40
|
+
// "consoleErrors": false,
|
|
41
|
+
// "maxFiles": 14,
|
|
42
|
+
// "maxSize": "50m",
|
|
43
|
+
// "flushInterval": 2000,
|
|
44
|
+
// "flushSize": 200
|
|
45
|
+
// }
|
|
46
|
+
// }
|
|
47
|
+
//
|
|
16
48
|
constructor(options = {}) {
|
|
17
|
-
this.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
maxSize: options.file?.maxSize || '20m',
|
|
27
|
-
maxFiles: options.file?.maxFiles || 14
|
|
28
|
-
}
|
|
29
|
-
};
|
|
49
|
+
this.level = options.level || DEFAULTS.level;
|
|
50
|
+
this.logDir = options.logDir || folders.logsDir();
|
|
51
|
+
this.maxFiles = options.maxFiles ?? DEFAULTS.maxFiles;
|
|
52
|
+
this.maxSize = Logger._parseSize(options.maxSize) || DEFAULTS.maxSize;
|
|
53
|
+
this.showConsole = options.console ?? DEFAULTS.console;
|
|
54
|
+
this.consoleErrors = options.consoleErrors ?? DEFAULTS.consoleErrors;
|
|
55
|
+
|
|
56
|
+
const flushInterval = options.flushInterval ?? DEFAULTS.flushInterval;
|
|
57
|
+
this._flushSize = options.flushSize ?? DEFAULTS.flushSize;
|
|
30
58
|
|
|
31
59
|
// Ensure log directory exists
|
|
32
|
-
if (!fs.existsSync(this.
|
|
33
|
-
fs.mkdirSync(this.
|
|
60
|
+
if (!fs.existsSync(this.logDir)) {
|
|
61
|
+
fs.mkdirSync(this.logDir, { recursive: true });
|
|
34
62
|
}
|
|
35
63
|
|
|
36
|
-
//
|
|
37
|
-
this.
|
|
64
|
+
// Buffer
|
|
65
|
+
this._buffer = [];
|
|
66
|
+
this._currentDate = null;
|
|
67
|
+
this._fd = null;
|
|
68
|
+
this._currentFileSize = 0;
|
|
38
69
|
|
|
39
|
-
|
|
70
|
+
// Periodic flush
|
|
71
|
+
this._flushTimer = setInterval(() => this._flush(), flushInterval);
|
|
72
|
+
if (this._flushTimer.unref) this._flushTimer.unref(); // don't keep process alive
|
|
40
73
|
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
});
|
|
74
|
+
// Flush on exit
|
|
75
|
+
process.on('exit', () => this._flushSync());
|
|
76
|
+
|
|
77
|
+
this.info('Logger initialized @ ' + this.logDir, {});
|
|
46
78
|
}
|
|
47
79
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
]
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// Add file transport with rotation (includes ALL levels with full metadata)
|
|
61
|
-
const fileTransport = new winston.transports.DailyRotateFile({
|
|
62
|
-
dirname: this.options.logDir,
|
|
63
|
-
filename: this.options.file.filename,
|
|
64
|
-
datePattern: this.options.file.datePattern,
|
|
65
|
-
maxSize: this.options.file.maxSize,
|
|
66
|
-
maxFiles: this.options.file.maxFiles,
|
|
67
|
-
level: this.options.level,
|
|
68
|
-
format: winston.format.combine(...fileFormats)
|
|
69
|
-
});
|
|
70
|
-
transports.push(fileTransport);
|
|
71
|
-
|
|
72
|
-
// Add console transport if enabled
|
|
73
|
-
if (this.options.console) {
|
|
74
|
-
const consoleFormat = winston.format.combine(
|
|
75
|
-
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
|
|
76
|
-
winston.format.errors({ stack: true }),
|
|
77
|
-
winston.format.colorize({ all: true }),
|
|
78
|
-
winston.format.printf(info => {
|
|
79
|
-
const stack = info.stack ? `\n${info.stack}` : '';
|
|
80
|
-
return `${info.timestamp} ${info.level.padEnd(7)} ${info.message}${stack}`;
|
|
81
|
-
})
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
const consoleTransport = new winston.transports.Console({
|
|
85
|
-
level: this.options.level,
|
|
86
|
-
format: consoleFormat
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
transports.push(consoleTransport);
|
|
80
|
+
// Parse human-readable size strings: "20m" -> bytes, "1g" -> bytes
|
|
81
|
+
static _parseSize(value) {
|
|
82
|
+
if (!value) return 0;
|
|
83
|
+
if (typeof value === 'number') return value;
|
|
84
|
+
const m = String(value).match(/^(\d+(?:\.\d+)?)\s*([kmg])?b?$/i);
|
|
85
|
+
if (!m) return 0;
|
|
86
|
+
const num = parseFloat(m[1]);
|
|
87
|
+
switch ((m[2] || '').toLowerCase()) {
|
|
88
|
+
case 'k': return num * 1024;
|
|
89
|
+
case 'm': return num * 1024 * 1024;
|
|
90
|
+
case 'g': return num * 1024 * 1024 * 1024;
|
|
91
|
+
default: return num;
|
|
90
92
|
}
|
|
93
|
+
}
|
|
91
94
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
// Compatibility: server.js home page reads Logger.getInstance().options.file.maxFiles etc.
|
|
96
|
+
get options() {
|
|
97
|
+
return {
|
|
98
|
+
level: this.level,
|
|
99
|
+
file: {
|
|
100
|
+
maxFiles: this.maxFiles,
|
|
101
|
+
maxSize: this.maxSize > 0 ? `${Math.round(this.maxSize / 1024 / 1024)}m` : 'unlimited',
|
|
102
|
+
}
|
|
103
|
+
};
|
|
98
104
|
}
|
|
99
105
|
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
// --- formatting (inline, no libraries) ---
|
|
107
|
+
|
|
108
|
+
_timestamp() {
|
|
109
|
+
const d = new Date();
|
|
110
|
+
const Y = d.getFullYear();
|
|
111
|
+
const M = String(d.getMonth() + 1).padStart(2, '0');
|
|
112
|
+
const D = String(d.getDate()).padStart(2, '0');
|
|
113
|
+
const h = String(d.getHours()).padStart(2, '0');
|
|
114
|
+
const m = String(d.getMinutes()).padStart(2, '0');
|
|
115
|
+
const s = String(d.getSeconds()).padStart(2, '0');
|
|
116
|
+
const ms = String(d.getMilliseconds()).padStart(3, '0');
|
|
117
|
+
return `${Y}-${M}-${D} ${h}:${m}:${s}.${ms}`;
|
|
103
118
|
}
|
|
104
119
|
|
|
105
|
-
|
|
106
|
-
|
|
120
|
+
_dateTag() {
|
|
121
|
+
const d = new Date();
|
|
122
|
+
const Y = d.getFullYear();
|
|
123
|
+
const M = String(d.getMonth() + 1).padStart(2, '0');
|
|
124
|
+
const D = String(d.getDate()).padStart(2, '0');
|
|
125
|
+
return `${Y}-${M}-${D}`;
|
|
107
126
|
}
|
|
108
127
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
128
|
+
_formatLine(level, message, stack) {
|
|
129
|
+
const ts = this._timestamp();
|
|
130
|
+
const lv = level.padEnd(7);
|
|
131
|
+
let line = `${ts} ${lv} ${message}\n`;
|
|
132
|
+
if (stack) line += stack + '\n';
|
|
133
|
+
return line;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// --- file management ---
|
|
114
137
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
138
|
+
_openFile(dateTag) {
|
|
139
|
+
// Check if we need to rotate due to size
|
|
140
|
+
if (this._fd !== null && this._currentDate === dateTag) {
|
|
141
|
+
if (this.maxSize <= 0 || this._currentFileSize < this.maxSize) return;
|
|
142
|
+
// Size limit exceeded — close and fall through to open a new file
|
|
143
|
+
try { fs.closeSync(this._fd); } catch (_) { /* intentional */ }
|
|
144
|
+
this._fd = null;
|
|
119
145
|
}
|
|
146
|
+
// Close previous (date changed)
|
|
147
|
+
if (this._fd !== null) {
|
|
148
|
+
try { fs.closeSync(this._fd); } catch (_) { /* intentional */ }
|
|
149
|
+
}
|
|
150
|
+
const filename = `server-${dateTag}.log`;
|
|
151
|
+
const filePath = path.join(this.logDir, filename);
|
|
152
|
+
this._fd = fs.openSync(filePath, 'a');
|
|
153
|
+
try { this._currentFileSize = fs.fstatSync(this._fd).size; } catch (_) { this._currentFileSize = 0; }
|
|
154
|
+
this._currentDate = dateTag;
|
|
155
|
+
|
|
156
|
+
// Maintain a stable symlink so `tail -f server.log` always tracks the current file
|
|
157
|
+
const linkPath = path.join(this.logDir, 'server.log');
|
|
158
|
+
try { fs.unlinkSync(linkPath); } catch (_) { /* intentional */ }
|
|
159
|
+
try { fs.symlinkSync(filename, linkPath); } catch (_) { /* intentional */ }
|
|
160
|
+
|
|
161
|
+
this._purgeOldFiles();
|
|
162
|
+
}
|
|
120
163
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
164
|
+
_purgeOldFiles() {
|
|
165
|
+
try {
|
|
166
|
+
const files = fs.readdirSync(this.logDir)
|
|
167
|
+
.filter(f => f.startsWith('server-') && f.endsWith('.log'))
|
|
168
|
+
.sort();
|
|
169
|
+
while (files.length > this.maxFiles) {
|
|
170
|
+
const old = files.shift();
|
|
171
|
+
fs.unlinkSync(path.join(this.logDir, old));
|
|
127
172
|
}
|
|
128
|
-
}
|
|
173
|
+
} catch (_) { /* intentional */ }
|
|
129
174
|
}
|
|
130
175
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
176
|
+
// --- buffer + flush ---
|
|
177
|
+
|
|
178
|
+
_enqueue(line) {
|
|
179
|
+
this._buffer.push(line);
|
|
180
|
+
if (this._buffer.length >= this._flushSize) {
|
|
181
|
+
this._flush();
|
|
134
182
|
}
|
|
135
|
-
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
_flush() {
|
|
186
|
+
if (this._buffer.length === 0) return;
|
|
187
|
+
const dateTag = this._dateTag();
|
|
188
|
+
this._openFile(dateTag);
|
|
189
|
+
const chunk = this._buffer.join('');
|
|
190
|
+
this._buffer.length = 0;
|
|
191
|
+
// Async write — fire and forget; OS will buffer anyway
|
|
192
|
+
const buf = Buffer.from(chunk);
|
|
193
|
+
this._currentFileSize += buf.length;
|
|
194
|
+
fs.write(this._fd, buf, 0, buf.length, null, (err) => {
|
|
195
|
+
if (err) {
|
|
196
|
+
// If the fd went bad (e.g. date rolled), reopen and retry once
|
|
197
|
+
try {
|
|
198
|
+
this._currentDate = null;
|
|
199
|
+
this._openFile(this._dateTag());
|
|
200
|
+
fs.writeSync(this._fd, buf, 0, buf.length);
|
|
201
|
+
} catch (_) { /* intentional */ }
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
_flushSync() {
|
|
207
|
+
if (this._buffer.length === 0) return;
|
|
208
|
+
const dateTag = this._dateTag();
|
|
209
|
+
this._openFile(dateTag);
|
|
210
|
+
const chunk = this._buffer.join('');
|
|
211
|
+
this._buffer.length = 0;
|
|
212
|
+
try { fs.writeSync(this._fd, chunk); } catch (_) { /* intentional */ }
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// --- core log ---
|
|
216
|
+
|
|
217
|
+
_shouldLog(level) {
|
|
218
|
+
return (LEVELS[level] ?? 99) <= (LEVELS[this.level] ?? 2);
|
|
136
219
|
}
|
|
137
220
|
|
|
138
221
|
_log(level, messageOrError, meta, options) {
|
|
222
|
+
if (!this._shouldLog(level)) return;
|
|
223
|
+
|
|
139
224
|
let message;
|
|
140
225
|
let stack;
|
|
141
226
|
|
|
142
|
-
// Check if we should skip console for errors/warnings
|
|
143
|
-
const skipConsole = !this._shouldLogToConsole(level, options);
|
|
144
|
-
|
|
145
|
-
// Handle Error objects
|
|
146
227
|
if (messageOrError instanceof Error) {
|
|
147
228
|
message = messageOrError.message;
|
|
148
229
|
stack = messageOrError.stack;
|
|
149
|
-
if (skipConsole) {
|
|
150
|
-
// Log only to file transport
|
|
151
|
-
this.logger.transports
|
|
152
|
-
.filter(t => !(t instanceof winston.transports.Console))
|
|
153
|
-
.forEach(t => t.log({ level, message, stack, ...meta }));
|
|
154
|
-
} else {
|
|
155
|
-
this.logger[level](message, {stack, ...meta});
|
|
156
|
-
}
|
|
157
230
|
} else {
|
|
158
231
|
message = String(messageOrError);
|
|
159
232
|
stack = meta?.stack;
|
|
160
|
-
if (skipConsole) {
|
|
161
|
-
this.logger.transports
|
|
162
|
-
.filter(t => !(t instanceof winston.transports.Console))
|
|
163
|
-
.forEach(t => t.log({ level, message, ...meta }));
|
|
164
|
-
} else {
|
|
165
|
-
this.logger[level](message, meta);
|
|
166
|
-
}
|
|
167
233
|
}
|
|
168
234
|
|
|
169
|
-
this.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
235
|
+
const line = this._formatLine(level, message, stack);
|
|
236
|
+
|
|
237
|
+
// Buffer for file
|
|
238
|
+
this._enqueue(line);
|
|
239
|
+
|
|
240
|
+
// Console
|
|
241
|
+
if (this.showConsole) {
|
|
242
|
+
const isErrWarn = level === 'error' || level === 'warn';
|
|
243
|
+
const consoleErrors = options?.consoleErrors ?? this.consoleErrors;
|
|
244
|
+
if (!isErrWarn || consoleErrors) {
|
|
245
|
+
if (isErrWarn) {
|
|
246
|
+
process.stderr.write(line);
|
|
247
|
+
} else {
|
|
248
|
+
process.stdout.write(line);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
182
252
|
}
|
|
183
253
|
|
|
184
|
-
|
|
185
|
-
this._log('debug', message, meta, this.options);
|
|
186
|
-
}
|
|
254
|
+
// --- public API (same as before) ---
|
|
187
255
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
256
|
+
error(message, meta = {}) { this._log('error', message, meta, this); }
|
|
257
|
+
warn(message, meta = {}) { this._log('warn', message, meta, this); }
|
|
258
|
+
info(message, meta = {}) { this._log('info', message, meta, this); }
|
|
259
|
+
debug(message, meta = {}) { this._log('debug', message, meta, this); }
|
|
260
|
+
verbose(message, meta = {}) { this._log('verbose', message, meta, this); }
|
|
191
261
|
|
|
192
|
-
log(level, message, meta = {}) {
|
|
193
|
-
this._log(level, message, meta, this.options);
|
|
194
|
-
}
|
|
262
|
+
log(level, message, meta = {}) { this._log(level, message, meta, this); }
|
|
195
263
|
|
|
196
264
|
child(defaultMeta = {}) {
|
|
197
265
|
const self = this;
|
|
198
266
|
|
|
199
|
-
// Build module-specific options
|
|
200
267
|
const childOptions = {
|
|
201
|
-
consoleErrors: defaultMeta.consoleErrors ?? self.
|
|
202
|
-
telnetErrors: defaultMeta.telnetErrors ?? self.options.telnetErrors
|
|
268
|
+
consoleErrors: defaultMeta.consoleErrors ?? self.consoleErrors,
|
|
203
269
|
};
|
|
204
270
|
|
|
205
|
-
|
|
206
|
-
const cleanMeta = { ...defaultMeta };
|
|
207
|
-
delete cleanMeta.consoleErrors;
|
|
208
|
-
delete cleanMeta.telnetErrors;
|
|
209
|
-
|
|
210
|
-
if (cleanMeta.module) {
|
|
211
|
-
const modulePrefix = `{${cleanMeta.module}}`;
|
|
212
|
-
|
|
213
|
-
return {
|
|
214
|
-
error: (messageOrError, meta = {}) => {
|
|
215
|
-
if (messageOrError instanceof Error) {
|
|
216
|
-
const prefixedError = new Error(`${modulePrefix}: ${messageOrError.message}`);
|
|
217
|
-
prefixedError.stack = messageOrError.stack;
|
|
218
|
-
self._log('error', prefixedError, meta, childOptions);
|
|
219
|
-
} else {
|
|
220
|
-
self._log('error', `${modulePrefix}: ${messageOrError}`, meta, childOptions);
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
warn: (messageOrError, meta = {}) => {
|
|
224
|
-
if (messageOrError instanceof Error) {
|
|
225
|
-
const prefixedError = new Error(`${modulePrefix}: ${messageOrError.message}`);
|
|
226
|
-
prefixedError.stack = messageOrError.stack;
|
|
227
|
-
self._log('warn', prefixedError, meta, childOptions);
|
|
228
|
-
} else {
|
|
229
|
-
self._log('warn', `${modulePrefix}: ${messageOrError}`, meta, childOptions);
|
|
230
|
-
}
|
|
231
|
-
},
|
|
232
|
-
info: (message, meta = {}) => self._log('info', `${modulePrefix}: ${message}`, meta, childOptions),
|
|
233
|
-
debug: (message, meta = {}) => self._log('debug', `${modulePrefix}: ${message}`, meta, childOptions),
|
|
234
|
-
verbose: (message, meta = {}) => self._log('verbose', `${modulePrefix}: ${message}`, meta, childOptions),
|
|
235
|
-
log: (level, message, meta = {}) => self._log(level, `${modulePrefix}: ${message}`, meta, childOptions)
|
|
236
|
-
};
|
|
237
|
-
}
|
|
271
|
+
const modulePrefix = defaultMeta.module ? `{${defaultMeta.module}}` : null;
|
|
238
272
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
273
|
+
const wrap = (level) => (messageOrError, meta = {}) => {
|
|
274
|
+
if (messageOrError instanceof Error) {
|
|
275
|
+
const prefixed = modulePrefix
|
|
276
|
+
? Object.assign(new Error(`${modulePrefix}: ${messageOrError.message}`), { stack: messageOrError.stack })
|
|
277
|
+
: messageOrError;
|
|
278
|
+
self._log(level, prefixed, meta, childOptions);
|
|
279
|
+
} else {
|
|
280
|
+
const msg = modulePrefix ? `${modulePrefix}: ${messageOrError}` : String(messageOrError);
|
|
281
|
+
self._log(level, msg, meta, childOptions);
|
|
282
|
+
}
|
|
247
283
|
};
|
|
248
284
|
|
|
249
|
-
return
|
|
285
|
+
return {
|
|
286
|
+
error: wrap('error'),
|
|
287
|
+
warn: wrap('warn'),
|
|
288
|
+
info: wrap('info'),
|
|
289
|
+
debug: wrap('debug'),
|
|
290
|
+
verbose: wrap('verbose'),
|
|
291
|
+
log: (level, message, meta = {}) => wrap(level)(message, meta)
|
|
292
|
+
};
|
|
250
293
|
}
|
|
251
294
|
|
|
252
295
|
setLevel(level) {
|
|
253
|
-
this.
|
|
254
|
-
this.logger.transports.forEach(transport => {
|
|
255
|
-
transport.level = level;
|
|
256
|
-
});
|
|
296
|
+
this.level = level;
|
|
257
297
|
this.info(`Log level changed to ${level}`);
|
|
258
298
|
}
|
|
259
299
|
|
|
260
300
|
setConsoleErrors(enabled) {
|
|
261
|
-
this.
|
|
301
|
+
this.consoleErrors = enabled;
|
|
262
302
|
this.info(`Console errors ${enabled ? 'enabled' : 'disabled'}`);
|
|
263
303
|
}
|
|
264
304
|
|
|
265
|
-
setTelnetErrors(enabled) {
|
|
266
|
-
this.options.telnetErrors = enabled;
|
|
267
|
-
this.info(`Telnet errors ${enabled ? 'enabled' : 'disabled'}`);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
305
|
stream() {
|
|
271
306
|
return {
|
|
272
307
|
write: (message) => {
|
|
@@ -274,6 +309,11 @@ class Logger {
|
|
|
274
309
|
}
|
|
275
310
|
};
|
|
276
311
|
}
|
|
312
|
+
|
|
313
|
+
// Force an immediate flush (e.g. before graceful shutdown)
|
|
314
|
+
flush() {
|
|
315
|
+
this._flushSync();
|
|
316
|
+
}
|
|
277
317
|
}
|
|
278
318
|
|
|
279
319
|
module.exports = Logger;
|
package/package.json
CHANGED
|
@@ -92,7 +92,9 @@
|
|
|
92
92
|
<p>
|
|
93
93
|
<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+. |
|
|
94
94
|
<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+ |
|
|
95
|
-
Package Registry last updated as of [%crawler-date%] | [%total-packages%] packages  
|
|
95
|
+
Package Registry last updated as of [%crawler-date%] | [%total-packages%] packages |
|
|
96
|
+
([%ms%] ms)
|
|
97
|
+
[%sponsorMessage%]
|
|
96
98
|
</p>
|
|
97
99
|
</div> <!-- /inner-wrapper -->
|
|
98
100
|
</div> <!-- /container -->
|
|
@@ -123,6 +123,7 @@
|
|
|
123
123
|
<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+. |
|
|
124
124
|
<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+ |
|
|
125
125
|
([%ms%] ms)
|
|
126
|
+
[%sponsorMessage%]
|
|
126
127
|
</p>
|
|
127
128
|
</div> <!-- /inner-wrapper -->
|
|
128
129
|
</div> <!-- /container -->
|
|
@@ -92,7 +92,9 @@
|
|
|
92
92
|
<p>
|
|
93
93
|
<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+. |
|
|
94
94
|
<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+ |
|
|
95
|
-
Terminology Registry last updated as of [%crawler-date%] | [%total-packages%] packages  
|
|
95
|
+
Terminology Registry last updated as of [%crawler-date%] | [%total-packages%] packages |
|
|
96
|
+
([%ms%] ms)
|
|
97
|
+
[%sponsorMessage%]
|
|
96
98
|
</p>
|
|
97
99
|
</div> <!-- /inner-wrapper -->
|
|
98
100
|
</div> <!-- /container -->
|
package/root-template.html
CHANGED
|
@@ -90,8 +90,9 @@
|
|
|
90
90
|
<div class="inner-wrapper">
|
|
91
91
|
<p>
|
|
92
92
|
<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+. |
|
|
93
|
-
<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+  
|
|
94
|
-
|
|
93
|
+
<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+ |
|
|
94
|
+
([%ms%] ms)
|
|
95
|
+
[%sponsorMessage%]
|
|
95
96
|
</p>
|
|
96
97
|
</div> <!-- /inner-wrapper -->
|
|
97
98
|
</div> <!-- /container -->
|