sof-mssql 2.3.0 → 2.4.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/README.md +88 -0
- package/dist/fhirpath/jsonSafeEmptiness.test.d.ts +19 -0
- package/dist/fhirpath/jsonSafeEmptiness.test.d.ts.map +1 -0
- package/dist/fhirpath/jsonSafeEmptiness.test.js +80 -0
- package/dist/fhirpath/jsonSafeEmptiness.test.js.map +1 -0
- package/dist/fhirpath/visitor.d.ts.map +1 -1
- package/dist/fhirpath/visitor.js +20 -12
- package/dist/fhirpath/visitor.js.map +1 -1
- package/dist/load.d.ts +9 -0
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js +4 -0
- package/dist/load.js.map +1 -1
- package/dist/loader/feedback.integration.test.d.ts +14 -0
- package/dist/loader/feedback.integration.test.d.ts.map +1 -0
- package/dist/loader/feedback.integration.test.js +76 -0
- package/dist/loader/feedback.integration.test.js.map +1 -0
- package/dist/loader/index.d.ts.map +1 -1
- package/dist/loader/index.js +19 -6
- package/dist/loader/index.js.map +1 -1
- package/dist/loader/jsonColumn.integration.test.d.ts +13 -0
- package/dist/loader/jsonColumn.integration.test.d.ts.map +1 -0
- package/dist/loader/jsonColumn.integration.test.js +86 -0
- package/dist/loader/jsonColumn.integration.test.js.map +1 -0
- package/dist/loader/tables.d.ts +96 -3
- package/dist/loader/tables.d.ts.map +1 -1
- package/dist/loader/tables.js +182 -16
- package/dist/loader/tables.js.map +1 -1
- package/dist/loader/tables.test.d.ts +12 -0
- package/dist/loader/tables.test.d.ts.map +1 -0
- package/dist/loader/tables.test.js +130 -0
- package/dist/loader/tables.test.js.map +1 -0
- package/dist/loader/types.d.ts +9 -0
- package/dist/loader/types.d.ts.map +1 -1
- package/dist/tests/load.test.d.ts +11 -0
- package/dist/tests/load.test.d.ts.map +1 -0
- package/dist/tests/load.test.js +37 -0
- package/dist/tests/load.test.js.map +1 -0
- package/dist/tests/utils/database.d.ts.map +1 -1
- package/dist/tests/utils/database.js +51 -3
- package/dist/tests/utils/database.js.map +1 -1
- package/dist/tests/utils/loaderIntegration.d.ts +59 -0
- package/dist/tests/utils/loaderIntegration.d.ts.map +1 -0
- package/dist/tests/utils/loaderIntegration.js +137 -0
- package/dist/tests/utils/loaderIntegration.js.map +1 -0
- package/dist/tests/utils/serverCapabilities.d.ts +23 -0
- package/dist/tests/utils/serverCapabilities.d.ts.map +1 -0
- package/dist/tests/utils/serverCapabilities.js +35 -0
- package/dist/tests/utils/serverCapabilities.js.map +1 -0
- package/dist/tests/validation.test.d.ts +13 -0
- package/dist/tests/validation.test.d.ts.map +1 -0
- package/dist/tests/validation.test.js +81 -0
- package/dist/tests/validation.test.js.map +1 -0
- package/dist/validation.d.ts +40 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +56 -0
- package/dist/validation.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Integration tests for misconfiguration feedback (US4).
|
|
4
|
+
*
|
|
5
|
+
* Covers: invalid values rejected before any connection is opened (FR-003,
|
|
6
|
+
* runs without a database); an existing-table type mismatch emitting a warning
|
|
7
|
+
* and leaving the table unaltered (FR-008, runs on any server); and the SQL
|
|
8
|
+
* Server "unsupported type" error being surfaced rather than swallowed when
|
|
9
|
+
* JSON is requested on a server that does not support it (FR-009, runs only on
|
|
10
|
+
* pre-2025 servers).
|
|
11
|
+
*
|
|
12
|
+
* @author John Grimes
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const vitest_1 = require("vitest");
|
|
16
|
+
const index_1 = require("./index");
|
|
17
|
+
const loaderIntegration_1 = require("../tests/utils/loaderIntegration");
|
|
18
|
+
const harness = (0, loaderIntegration_1.createLoaderIntegrationHarness)();
|
|
19
|
+
(0, vitest_1.beforeAll)(() => harness.connect());
|
|
20
|
+
(0, vitest_1.afterAll)(() => harness.cleanup());
|
|
21
|
+
(0, vitest_1.describe)("invalid resourceJsonDataType (US4, no database required)", () => {
|
|
22
|
+
(0, vitest_1.it)("throws before opening a connection", async () => {
|
|
23
|
+
// The database host is unroutable. If validation did not run first, the
|
|
24
|
+
// call would fail with a connection error; instead it must fail with the
|
|
25
|
+
// validation error, proving no connection was attempted (FR-003).
|
|
26
|
+
await (0, vitest_1.expect)((0, index_1.loadNdjsonFiles)({
|
|
27
|
+
directory: "/nonexistent-directory",
|
|
28
|
+
database: {
|
|
29
|
+
host: "203.0.113.1",
|
|
30
|
+
user: "unused",
|
|
31
|
+
password: "unused",
|
|
32
|
+
database: "unused",
|
|
33
|
+
},
|
|
34
|
+
resourceJsonDataType: "TEXT",
|
|
35
|
+
})).rejects.toThrow(/Invalid resource JSON data type.*TEXT/s);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.describe)("existing-table type mismatch (US4)", () => {
|
|
39
|
+
(0, vitest_1.it)("warns naming both types and does not alter the existing table", async () => {
|
|
40
|
+
// First load creates the table as the default NVARCHAR(MAX).
|
|
41
|
+
const tableName = harness.makeTableName();
|
|
42
|
+
await harness.loadSample(tableName);
|
|
43
|
+
// Second load requests JSON against the now-existing NVARCHAR(MAX) table.
|
|
44
|
+
const warnSpy = vitest_1.vi.spyOn(console, "warn").mockImplementation(() => { });
|
|
45
|
+
let warnings = [];
|
|
46
|
+
try {
|
|
47
|
+
await harness.loadSample(tableName, "JSON");
|
|
48
|
+
warnings = warnSpy.mock.calls.map((call) => call.join(" "));
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
warnSpy.mockRestore();
|
|
52
|
+
}
|
|
53
|
+
// A warning naming both the existing and requested types must be emitted.
|
|
54
|
+
const mismatchWarning = warnings.find((w) => w.includes("NVARCHAR(MAX)") &&
|
|
55
|
+
w.includes("JSON") &&
|
|
56
|
+
w.includes(tableName));
|
|
57
|
+
(0, vitest_1.expect)(mismatchWarning).toBeDefined();
|
|
58
|
+
// The table must be left unaltered (still NVARCHAR(MAX)).
|
|
59
|
+
const columnType = await harness.getJsonColumnType(tableName);
|
|
60
|
+
(0, vitest_1.expect)(columnType.dataType).toBe("nvarchar");
|
|
61
|
+
(0, vitest_1.expect)(columnType.maxLength).toBe(-1);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
(0, vitest_1.describe)("JSON requested on an unsupporting server (US4)", () => {
|
|
65
|
+
(0, vitest_1.it)("surfaces the SQL Server error rather than swallowing it", async (ctx) => {
|
|
66
|
+
// Only meaningful on servers without the native JSON type; on SQL Server
|
|
67
|
+
// 2025+ the request succeeds, so this is skipped there. CI exercises it on
|
|
68
|
+
// the 2017/2019/2022 matrix dimensions (FR-009).
|
|
69
|
+
if (harness.isNativeJsonSupported()) {
|
|
70
|
+
ctx.skip();
|
|
71
|
+
}
|
|
72
|
+
const tableName = harness.makeTableName();
|
|
73
|
+
await (0, vitest_1.expect)(harness.loadSample(tableName, "JSON")).rejects.toThrow();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=feedback.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feedback.integration.test.js","sourceRoot":"","sources":["../../src/loader/feedback.integration.test.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AAEH,mCAAuE;AACvE,mCAA0C;AAC1C,wEAAkF;AAElF,MAAM,OAAO,GAAG,IAAA,kDAA8B,GAAE,CAAC;AAEjD,IAAA,kBAAS,EAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AACnC,IAAA,iBAAQ,EAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AAElC,IAAA,iBAAQ,EAAC,0DAA0D,EAAE,GAAG,EAAE;IACxE,IAAA,WAAE,EAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,wEAAwE;QACxE,yEAAyE;QACzE,kEAAkE;QAClE,MAAM,IAAA,eAAM,EACV,IAAA,uBAAe,EAAC;YACd,SAAS,EAAE,wBAAwB;YACnC,QAAQ,EAAE;gBACR,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,QAAQ;gBAClB,QAAQ,EAAE,QAAQ;aACnB;YACD,oBAAoB,EAAE,MAAM;SAC7B,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,IAAA,WAAE,EAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,6DAA6D;QAC7D,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1C,MAAM,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAEpC,0EAA0E;QAC1E,MAAM,OAAO,GAAG,WAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACvE,IAAI,QAAQ,GAAa,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC5C,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9D,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,CAAC;QAED,0EAA0E;QAC1E,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC;YAC3B,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAClB,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CACxB,CAAC;QACF,IAAA,eAAM,EAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;QAEtC,0DAA0D;QAC1D,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC9D,IAAA,eAAM,EAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAA,eAAM,EAAC,UAAU,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,gDAAgD,EAAE,GAAG,EAAE;IAC9D,IAAA,WAAE,EAAC,yDAAyD,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC1E,yEAAyE;QACzE,2EAA2E;QAC3E,iDAAiD;QACjD,IAAI,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC;YACpC,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,CAAC;QACD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1C,MAAM,IAAA,eAAM,EAAC,OAAO,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loader/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAEV,aAAa,EAEb,aAAa,EACd,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loader/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAEV,aAAa,EAEb,aAAa,EACd,MAAM,YAAY,CAAC;AAkOpB;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,aAAa,CAAC,CAqCxB;AAED;;GAEG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
|
package/dist/loader/index.js
CHANGED
|
@@ -21,6 +21,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.loadNdjsonFiles = loadNdjsonFiles;
|
|
24
|
+
const validation_js_1 = require("../validation.js");
|
|
24
25
|
const connection_js_1 = require("./connection.js");
|
|
25
26
|
const discovery_js_1 = require("./discovery.js");
|
|
26
27
|
const tables_js_1 = require("./tables.js");
|
|
@@ -74,14 +75,20 @@ function chunkFiles(files, chunkSize) {
|
|
|
74
75
|
* @param options - Loader options.
|
|
75
76
|
* @returns Table schema and name.
|
|
76
77
|
*/
|
|
77
|
-
async function prepareTable(pool, options) {
|
|
78
|
+
async function prepareTable(pool, options, jsonType) {
|
|
78
79
|
const schemaName = options.schemaName ?? "dbo";
|
|
79
80
|
const tableName = options.tableName ?? "fhir_resources";
|
|
80
81
|
if (options.createTable !== false) {
|
|
81
82
|
if (options.verbose) {
|
|
82
|
-
console.log(`Ensuring table [${schemaName}].[${tableName}] exists${options.truncate ? " (will truncate)" : ""}...`);
|
|
83
|
+
console.log(`Ensuring table [${schemaName}].[${tableName}] exists as [json] ${jsonType}${options.truncate ? " (will truncate)" : ""}...`);
|
|
83
84
|
}
|
|
84
|
-
await (0, tables_js_1.ensureTable)(pool, schemaName, tableName, options.truncate ?? false);
|
|
85
|
+
await (0, tables_js_1.ensureTable)(pool, schemaName, tableName, options.truncate ?? false, jsonType);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Table creation is disabled, so the requested type cannot be applied.
|
|
89
|
+
// Still surface a mismatch against an existing table so misconfiguration
|
|
90
|
+
// remains visible (FR-008 edge case).
|
|
91
|
+
await (0, tables_js_1.warnIfJsonTypeMismatch)(pool, schemaName, tableName, jsonType);
|
|
85
92
|
}
|
|
86
93
|
return { schemaName, tableName };
|
|
87
94
|
}
|
|
@@ -129,7 +136,7 @@ async function loadFilesInChunks(pool, files, options, schemaName, tableName, pr
|
|
|
129
136
|
* @param startTime - Start timestamp.
|
|
130
137
|
* @returns Loader summary.
|
|
131
138
|
*/
|
|
132
|
-
async function performLoad(pool, files, options, startTime) {
|
|
139
|
+
async function performLoad(pool, files, options, startTime, jsonType) {
|
|
133
140
|
const connected = await (0, connection_js_1.testConnection)(pool);
|
|
134
141
|
if (!connected) {
|
|
135
142
|
throw new Error("Failed to connect to database");
|
|
@@ -138,7 +145,7 @@ async function performLoad(pool, files, options, startTime) {
|
|
|
138
145
|
console.log("Connected successfully\n");
|
|
139
146
|
}
|
|
140
147
|
const progress = (0, progress_js_1.createProgressTracker)(files);
|
|
141
|
-
const { schemaName, tableName } = await prepareTable(pool, options);
|
|
148
|
+
const { schemaName, tableName } = await prepareTable(pool, options, jsonType);
|
|
142
149
|
if (!options.quiet) {
|
|
143
150
|
console.log("Loading files...\n");
|
|
144
151
|
}
|
|
@@ -160,6 +167,12 @@ async function performLoad(pool, files, options, startTime) {
|
|
|
160
167
|
*/
|
|
161
168
|
async function loadNdjsonFiles(options) {
|
|
162
169
|
const startTime = Date.now();
|
|
170
|
+
// Resolve and validate the json column storage type before any file
|
|
171
|
+
// discovery, connection or DDL. An invalid value throws synchronously here,
|
|
172
|
+
// so misconfiguration is reported before a connection is opened (FR-003).
|
|
173
|
+
const jsonType = options.resourceJsonDataType === undefined
|
|
174
|
+
? "NVARCHAR(MAX)"
|
|
175
|
+
: (0, validation_js_1.normaliseResourceJsonDataType)(options.resourceJsonDataType);
|
|
163
176
|
const files = discoverAndLogFiles(options);
|
|
164
177
|
if (files.length === 0) {
|
|
165
178
|
return (0, progress_js_1.createSummary)((0, progress_js_1.createProgressTracker)([]), Date.now() - startTime);
|
|
@@ -175,7 +188,7 @@ async function loadNdjsonFiles(options) {
|
|
|
175
188
|
}
|
|
176
189
|
const pool = await (0, connection_js_1.createConnectionPool)(options.database);
|
|
177
190
|
try {
|
|
178
|
-
return await performLoad(pool, files, options, startTime);
|
|
191
|
+
return await performLoad(pool, files, options, startTime, jsonType);
|
|
179
192
|
}
|
|
180
193
|
finally {
|
|
181
194
|
await (0, connection_js_1.closeConnectionPool)(pool);
|
package/dist/loader/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loader/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/loader/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database-backed integration tests for the configurable `json` column type.
|
|
3
|
+
*
|
|
4
|
+
* Exercises the loader end to end against a real SQL Server: the default
|
|
5
|
+
* `NVARCHAR(MAX)` column (US1, every supported version) and the native `JSON`
|
|
6
|
+
* column (US1/US2, SQL Server 2025+ only). The native-JSON cases skip
|
|
7
|
+
* automatically on servers that do not support the type, so the same file is
|
|
8
|
+
* safe to run across the whole CI matrix.
|
|
9
|
+
*
|
|
10
|
+
* @author John Grimes
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=jsonColumn.integration.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonColumn.integration.test.d.ts","sourceRoot":"","sources":["../../src/loader/jsonColumn.integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Database-backed integration tests for the configurable `json` column type.
|
|
4
|
+
*
|
|
5
|
+
* Exercises the loader end to end against a real SQL Server: the default
|
|
6
|
+
* `NVARCHAR(MAX)` column (US1, every supported version) and the native `JSON`
|
|
7
|
+
* column (US1/US2, SQL Server 2025+ only). The native-JSON cases skip
|
|
8
|
+
* automatically on servers that do not support the type, so the same file is
|
|
9
|
+
* safe to run across the whole CI matrix.
|
|
10
|
+
*
|
|
11
|
+
* @author John Grimes
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
const vitest_1 = require("vitest");
|
|
15
|
+
const loaderIntegration_1 = require("../tests/utils/loaderIntegration");
|
|
16
|
+
const harness = (0, loaderIntegration_1.createLoaderIntegrationHarness)();
|
|
17
|
+
(0, vitest_1.beforeAll)(() => harness.connect());
|
|
18
|
+
(0, vitest_1.afterAll)(() => harness.cleanup());
|
|
19
|
+
(0, vitest_1.describe)("loadNdjsonFiles json column type (US1)", () => {
|
|
20
|
+
(0, vitest_1.it)("creates an NVARCHAR(MAX) column and loads every row when the type is omitted", async () => {
|
|
21
|
+
// The default path must be unchanged from earlier releases (SC-001).
|
|
22
|
+
const tableName = harness.makeTableName();
|
|
23
|
+
const rowsLoaded = await harness.loadSample(tableName);
|
|
24
|
+
(0, vitest_1.expect)(rowsLoaded).toBe(loaderIntegration_1.SAMPLE_PATIENTS.length);
|
|
25
|
+
const columnType = await harness.getJsonColumnType(tableName);
|
|
26
|
+
(0, vitest_1.expect)(columnType.dataType).toBe("nvarchar");
|
|
27
|
+
(0, vitest_1.expect)(columnType.maxLength).toBe(-1);
|
|
28
|
+
(0, vitest_1.expect)(await harness.getRowCount(tableName)).toBe(loaderIntegration_1.SAMPLE_PATIENTS.length);
|
|
29
|
+
});
|
|
30
|
+
(0, vitest_1.it)("creates a native JSON column and loads every row when JSON is requested", async (ctx) => {
|
|
31
|
+
if (!harness.isNativeJsonSupported()) {
|
|
32
|
+
ctx.skip();
|
|
33
|
+
}
|
|
34
|
+
const tableName = harness.makeTableName();
|
|
35
|
+
const rowsLoaded = await harness.loadSample(tableName, "JSON");
|
|
36
|
+
(0, vitest_1.expect)(rowsLoaded).toBe(loaderIntegration_1.SAMPLE_PATIENTS.length);
|
|
37
|
+
const columnType = await harness.getJsonColumnType(tableName);
|
|
38
|
+
(0, vitest_1.expect)(columnType.dataType).toBe("json");
|
|
39
|
+
(0, vitest_1.expect)(await harness.getRowCount(tableName)).toBe(loaderIntegration_1.SAMPLE_PATIENTS.length);
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.it)("accepts a lower-case json value and still creates the native type", async (ctx) => {
|
|
42
|
+
if (!harness.isNativeJsonSupported()) {
|
|
43
|
+
ctx.skip();
|
|
44
|
+
}
|
|
45
|
+
const tableName = harness.makeTableName();
|
|
46
|
+
await harness.loadSample(tableName, "json");
|
|
47
|
+
const columnType = await harness.getJsonColumnType(tableName);
|
|
48
|
+
(0, vitest_1.expect)(columnType.dataType).toBe("json");
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
(0, vitest_1.describe)("loadNdjsonFiles json column type (US2 - programmatic, no CLI)", () => {
|
|
52
|
+
// loadSample calls loadNdjsonFiles with LoaderOptions directly, demonstrating
|
|
53
|
+
// that the capability is fully available through the programmatic API with no
|
|
54
|
+
// CLI or commander layer involved.
|
|
55
|
+
(0, vitest_1.it)("honours LoaderOptions.resourceJsonDataType = JSON via the programmatic API", async (ctx) => {
|
|
56
|
+
if (!harness.isNativeJsonSupported()) {
|
|
57
|
+
ctx.skip();
|
|
58
|
+
}
|
|
59
|
+
const tableName = harness.makeTableName();
|
|
60
|
+
const rowsLoaded = await harness.loadSample(tableName, "JSON");
|
|
61
|
+
(0, vitest_1.expect)(rowsLoaded).toBe(loaderIntegration_1.SAMPLE_PATIENTS.length);
|
|
62
|
+
const columnType = await harness.getJsonColumnType(tableName);
|
|
63
|
+
(0, vitest_1.expect)(columnType.dataType).toBe("json");
|
|
64
|
+
});
|
|
65
|
+
(0, vitest_1.it)("defaults to NVARCHAR(MAX) programmatically when the option is omitted", async () => {
|
|
66
|
+
const tableName = harness.makeTableName();
|
|
67
|
+
const rowsLoaded = await harness.loadSample(tableName);
|
|
68
|
+
(0, vitest_1.expect)(rowsLoaded).toBe(loaderIntegration_1.SAMPLE_PATIENTS.length);
|
|
69
|
+
const columnType = await harness.getJsonColumnType(tableName);
|
|
70
|
+
(0, vitest_1.expect)(columnType.dataType).toBe("nvarchar");
|
|
71
|
+
(0, vitest_1.expect)(columnType.maxLength).toBe(-1);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
(0, vitest_1.describe)("loadNdjsonFiles existing json column safeguard (FR-008)", () => {
|
|
75
|
+
(0, vitest_1.it)("fails fast when an existing json column cannot hold a FHIR resource", async () => {
|
|
76
|
+
// A pre-existing table whose json column is a bounded VARCHAR cannot hold a
|
|
77
|
+
// serialised FHIR resource. The loader must reject it before writing any
|
|
78
|
+
// rows, rather than coercing it to NVARCHAR(MAX) and corrupting data.
|
|
79
|
+
const tableName = harness.makeTableName();
|
|
80
|
+
await harness.createTableWithJsonColumnType(tableName, "VARCHAR(100)");
|
|
81
|
+
await (0, vitest_1.expect)(harness.loadSample(tableName)).rejects.toThrow(/VARCHAR\(100\)/);
|
|
82
|
+
// No rows must have been written into the unsafe column.
|
|
83
|
+
(0, vitest_1.expect)(await harness.getRowCount(tableName)).toBe(0);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=jsonColumn.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonColumn.integration.test.js","sourceRoot":"","sources":["../../src/loader/jsonColumn.integration.test.ts"],"names":[],"mappings":"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"}
|
package/dist/loader/tables.d.ts
CHANGED
|
@@ -5,6 +5,63 @@
|
|
|
5
5
|
* @author John Grimes
|
|
6
6
|
*/
|
|
7
7
|
import { type ConnectionPool } from "mssql";
|
|
8
|
+
import { type ResourceJsonDataType } from "../validation.js";
|
|
9
|
+
/**
|
|
10
|
+
* The DDL statements needed to create the resources table and its index.
|
|
11
|
+
*/
|
|
12
|
+
export interface CreateTableStatements {
|
|
13
|
+
/** The `CREATE TABLE` statement. */
|
|
14
|
+
createTable: string;
|
|
15
|
+
/** The `CREATE INDEX` statement for the `resource_type` column. */
|
|
16
|
+
createIndex: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build the DDL statements for the resources table and its index.
|
|
20
|
+
*
|
|
21
|
+
* This is a pure function so the generated SQL can be unit-tested without a
|
|
22
|
+
* database. The `json` column is typed with the resolved {@link
|
|
23
|
+
* ResourceJsonDataType}; with the default `NVARCHAR(MAX)` the output is
|
|
24
|
+
* byte-for-byte identical to earlier releases (SC-001). Identifiers are assumed
|
|
25
|
+
* to have been validated by the caller (see {@link createTable}).
|
|
26
|
+
*
|
|
27
|
+
* @param schemaName - Schema name (already validated).
|
|
28
|
+
* @param tableName - Table name (already validated).
|
|
29
|
+
* @param jsonType - Resolved canonical storage type for the `json` column.
|
|
30
|
+
* @returns The `CREATE TABLE` and `CREATE INDEX` statements.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildCreateTableStatements(schemaName: string, tableName: string, jsonType: ResourceJsonDataType): CreateTableStatements;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve an INFORMATION_SCHEMA column description to a canonical json type.
|
|
35
|
+
*
|
|
36
|
+
* Only two column shapes can faithfully hold a serialised FHIR resource: the
|
|
37
|
+
* native type (`data_type = 'json'`) and `NVARCHAR(MAX)` (`data_type =
|
|
38
|
+
* 'nvarchar'` with `character_maximum_length = -1`). Any other shape - a bounded
|
|
39
|
+
* `NVARCHAR(64)`, a non-Unicode `VARCHAR`, `TEXT`, and so on - is rejected here
|
|
40
|
+
* rather than silently coerced to `NVARCHAR(MAX)`. Coercion would let the
|
|
41
|
+
* mismatch check pass and the loader write into a column that cannot hold the
|
|
42
|
+
* data, surfacing later as a `String or binary data would be truncated` error
|
|
43
|
+
* or, under non-Unicode `VARCHAR`, silent character corruption. Failing fast
|
|
44
|
+
* turns that late, data-dependent failure into an early, actionable
|
|
45
|
+
* configuration error (Constitution Principle IV).
|
|
46
|
+
*
|
|
47
|
+
* @param dataType - The INFORMATION_SCHEMA DATA_TYPE.
|
|
48
|
+
* @param characterMaximumLength - The INFORMATION_SCHEMA CHARACTER_MAXIMUM_LENGTH.
|
|
49
|
+
* @returns The canonical resource json data type (`JSON` or `NVARCHAR(MAX)`).
|
|
50
|
+
* @throws Error if the column is neither native `JSON` nor `NVARCHAR(MAX)`. The
|
|
51
|
+
* message names the offending type and the two acceptable types.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveColumnJsonDataType(dataType: string, characterMaximumLength: number | null): ResourceJsonDataType;
|
|
54
|
+
/**
|
|
55
|
+
* Build a warning for an existing table whose json column type differs from the
|
|
56
|
+
* requested type.
|
|
57
|
+
*
|
|
58
|
+
* @param schemaName - Schema name.
|
|
59
|
+
* @param tableName - Table name.
|
|
60
|
+
* @param existingType - The table's current json column type.
|
|
61
|
+
* @param requestedType - The requested json column type.
|
|
62
|
+
* @returns A warning message naming both types, or null when they match.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildJsonTypeMismatchWarning(schemaName: string, tableName: string, existingType: ResourceJsonDataType, requestedType: ResourceJsonDataType): string | null;
|
|
8
65
|
/**
|
|
9
66
|
* Check if a table exists in the database.
|
|
10
67
|
*
|
|
@@ -14,15 +71,46 @@ import { type ConnectionPool } from "mssql";
|
|
|
14
71
|
* @returns Promise that resolves to true if the table exists.
|
|
15
72
|
*/
|
|
16
73
|
export declare function tableExists(pool: ConnectionPool, schemaName: string, tableName: string): Promise<boolean>;
|
|
74
|
+
/**
|
|
75
|
+
* Read the effective json column type for an existing table.
|
|
76
|
+
*
|
|
77
|
+
* @param pool - Database connection pool.
|
|
78
|
+
* @param schemaName - Schema name.
|
|
79
|
+
* @param tableName - Name of the table.
|
|
80
|
+
* @returns The canonical json column type, or null if the table or its `json`
|
|
81
|
+
* column does not exist.
|
|
82
|
+
* @throws Error if the column exists but is neither native `JSON` nor
|
|
83
|
+
* `NVARCHAR(MAX)` (see {@link resolveColumnJsonDataType}).
|
|
84
|
+
*/
|
|
85
|
+
export declare function getExistingJsonColumnType(pool: ConnectionPool, schemaName: string, tableName: string): Promise<ResourceJsonDataType | null>;
|
|
86
|
+
/**
|
|
87
|
+
* Emit a warning if an existing table's json column type differs from the
|
|
88
|
+
* requested type. The table is never altered; this only surfaces the mismatch
|
|
89
|
+
* so it is visible rather than silently ignored (FR-008, SC-005).
|
|
90
|
+
*
|
|
91
|
+
* An existing column that is neither native `JSON` nor `NVARCHAR(MAX)` cannot
|
|
92
|
+
* hold a serialised FHIR resource, so it is rejected outright rather than
|
|
93
|
+
* warned about: the error is raised here before any rows are loaded.
|
|
94
|
+
*
|
|
95
|
+
* @param pool - Database connection pool.
|
|
96
|
+
* @param schemaName - Schema name.
|
|
97
|
+
* @param tableName - Name of the table.
|
|
98
|
+
* @param requestedType - The requested json column type.
|
|
99
|
+
* @throws Error if the existing `json` column is neither native `JSON` nor
|
|
100
|
+
* `NVARCHAR(MAX)` (see {@link resolveColumnJsonDataType}).
|
|
101
|
+
*/
|
|
102
|
+
export declare function warnIfJsonTypeMismatch(pool: ConnectionPool, schemaName: string, tableName: string, requestedType: ResourceJsonDataType): Promise<void>;
|
|
17
103
|
/**
|
|
18
104
|
* Create the fhir_resources table with an index on resource_type.
|
|
19
|
-
* Table schema: id (INT IDENTITY PRIMARY KEY), resource_type (NVARCHAR(64)),
|
|
105
|
+
* Table schema: id (INT IDENTITY PRIMARY KEY), resource_type (NVARCHAR(64)),
|
|
106
|
+
* json (the configured storage type, NVARCHAR(MAX) by default).
|
|
20
107
|
*
|
|
21
108
|
* @param pool - Database connection pool.
|
|
22
109
|
* @param schemaName - Schema name.
|
|
23
110
|
* @param tableName - Name of the table to create.
|
|
111
|
+
* @param jsonType - Storage type for the `json` column (default `NVARCHAR(MAX)`).
|
|
24
112
|
*/
|
|
25
|
-
export declare function createTable(pool: ConnectionPool, schemaName: string, tableName: string): Promise<void>;
|
|
113
|
+
export declare function createTable(pool: ConnectionPool, schemaName: string, tableName: string, jsonType?: ResourceJsonDataType): Promise<void>;
|
|
26
114
|
/**
|
|
27
115
|
* Truncate a table (remove all rows).
|
|
28
116
|
*
|
|
@@ -34,10 +122,15 @@ export declare function truncateTable(pool: ConnectionPool, schemaName: string,
|
|
|
34
122
|
/**
|
|
35
123
|
* Ensure the fhir_resources table exists, creating it if necessary.
|
|
36
124
|
*
|
|
125
|
+
* When the table already exists it is never altered; the requested `json`
|
|
126
|
+
* column type only governs creation of a new table.
|
|
127
|
+
*
|
|
37
128
|
* @param pool - Database connection pool.
|
|
38
129
|
* @param schemaName - Schema name.
|
|
39
130
|
* @param tableName - Name of the table.
|
|
40
131
|
* @param truncate - Whether to truncate the table if it exists.
|
|
132
|
+
* @param jsonType - Storage type for the `json` column when creating the table
|
|
133
|
+
* (default `NVARCHAR(MAX)`).
|
|
41
134
|
*/
|
|
42
|
-
export declare function ensureTable(pool: ConnectionPool, schemaName: string, tableName: string, truncate?: boolean): Promise<void>;
|
|
135
|
+
export declare function ensureTable(pool: ConnectionPool, schemaName: string, tableName: string, truncate?: boolean, jsonType?: ResourceJsonDataType): Promise<void>;
|
|
43
136
|
//# sourceMappingURL=tables.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../src/loader/tables.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAY,EAAE,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../src/loader/tables.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAY,EAAE,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EACL,KAAK,oBAAoB,EAE1B,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,oBAAoB,GAC7B,qBAAqB,CAiBvB;AA0BD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,sBAAsB,EAAE,MAAM,GAAG,IAAI,GACpC,oBAAoB,CAgBtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,oBAAoB,EAClC,aAAa,EAAE,oBAAoB,GAClC,MAAM,GAAG,IAAI,CASf;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,cAAc,EACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,cAAc,EACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAiBtC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,cAAc,EACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,oBAAoB,GAClC,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,cAAc,EACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,oBAAsC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,cAAc,EACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,cAAc,EACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,OAAe,EACzB,QAAQ,GAAE,oBAAsC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAaf"}
|