sof-mssql 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/LICENSE +202 -0
- package/README.md +346 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +85 -0
- package/dist/cli.js.map +1 -0
- package/dist/fhirpath/transpiler.d.ts +18 -0
- package/dist/fhirpath/transpiler.d.ts.map +1 -0
- package/dist/fhirpath/transpiler.js +82 -0
- package/dist/fhirpath/transpiler.js.map +1 -0
- package/dist/fhirpath/visitor.d.ts +153 -0
- package/dist/fhirpath/visitor.d.ts.map +1 -0
- package/dist/fhirpath/visitor.js +1295 -0
- package/dist/fhirpath/visitor.js.map +1 -0
- package/dist/generated/grammar/fhirpathLexer.d.ts +88 -0
- package/dist/generated/grammar/fhirpathLexer.d.ts.map +1 -0
- package/dist/generated/grammar/fhirpathLexer.js +598 -0
- package/dist/generated/grammar/fhirpathLexer.js.map +1 -0
- package/dist/generated/grammar/fhirpathListener.d.ts +589 -0
- package/dist/generated/grammar/fhirpathListener.d.ts.map +1 -0
- package/dist/generated/grammar/fhirpathListener.js +4 -0
- package/dist/generated/grammar/fhirpathListener.js.map +1 -0
- package/dist/generated/grammar/fhirpathParser.d.ts +470 -0
- package/dist/generated/grammar/fhirpathParser.d.ts.map +1 -0
- package/dist/generated/grammar/fhirpathParser.js +3022 -0
- package/dist/generated/grammar/fhirpathParser.js.map +1 -0
- package/dist/generated/grammar/fhirpathVisitor.d.ts +372 -0
- package/dist/generated/grammar/fhirpathVisitor.d.ts.map +1 -0
- package/dist/generated/grammar/fhirpathVisitor.js +4 -0
- package/dist/generated/grammar/fhirpathVisitor.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/load.d.ts +14 -0
- package/dist/load.d.ts.map +1 -0
- package/dist/load.js +115 -0
- package/dist/load.js.map +1 -0
- package/dist/loader/connection.d.ts +36 -0
- package/dist/loader/connection.d.ts.map +1 -0
- package/dist/loader/connection.js +106 -0
- package/dist/loader/connection.js.map +1 -0
- package/dist/loader/discovery.d.ts +38 -0
- package/dist/loader/discovery.d.ts.map +1 -0
- package/dist/loader/discovery.js +107 -0
- package/dist/loader/discovery.js.map +1 -0
- package/dist/loader/index.d.ts +24 -0
- package/dist/loader/index.d.ts.map +1 -0
- package/dist/loader/index.js +193 -0
- package/dist/loader/index.js.map +1 -0
- package/dist/loader/progress.d.ts +70 -0
- package/dist/loader/progress.d.ts.map +1 -0
- package/dist/loader/progress.js +206 -0
- package/dist/loader/progress.js.map +1 -0
- package/dist/loader/stream.d.ts +21 -0
- package/dist/loader/stream.d.ts.map +1 -0
- package/dist/loader/stream.js +103 -0
- package/dist/loader/stream.js.map +1 -0
- package/dist/loader/tables.d.ts +43 -0
- package/dist/loader/tables.d.ts.map +1 -0
- package/dist/loader/tables.js +88 -0
- package/dist/loader/tables.js.map +1 -0
- package/dist/loader/types.d.ts +134 -0
- package/dist/loader/types.d.ts.map +1 -0
- package/dist/loader/types.js +8 -0
- package/dist/loader/types.js.map +1 -0
- package/dist/parser.d.ts +60 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +226 -0
- package/dist/parser.js.map +1 -0
- package/dist/queryGenerator/ColumnExpressionGenerator.d.ts +52 -0
- package/dist/queryGenerator/ColumnExpressionGenerator.d.ts.map +1 -0
- package/dist/queryGenerator/ColumnExpressionGenerator.js +144 -0
- package/dist/queryGenerator/ColumnExpressionGenerator.js.map +1 -0
- package/dist/queryGenerator/ForEachProcessor.d.ts +127 -0
- package/dist/queryGenerator/ForEachProcessor.d.ts.map +1 -0
- package/dist/queryGenerator/ForEachProcessor.js +351 -0
- package/dist/queryGenerator/ForEachProcessor.js.map +1 -0
- package/dist/queryGenerator/PathParser.d.ts +64 -0
- package/dist/queryGenerator/PathParser.d.ts.map +1 -0
- package/dist/queryGenerator/PathParser.js +164 -0
- package/dist/queryGenerator/PathParser.js.map +1 -0
- package/dist/queryGenerator/SelectClauseBuilder.d.ts +63 -0
- package/dist/queryGenerator/SelectClauseBuilder.d.ts.map +1 -0
- package/dist/queryGenerator/SelectClauseBuilder.js +196 -0
- package/dist/queryGenerator/SelectClauseBuilder.js.map +1 -0
- package/dist/queryGenerator/SelectCombinationExpander.d.ts +42 -0
- package/dist/queryGenerator/SelectCombinationExpander.d.ts.map +1 -0
- package/dist/queryGenerator/SelectCombinationExpander.js +95 -0
- package/dist/queryGenerator/SelectCombinationExpander.js.map +1 -0
- package/dist/queryGenerator/WhereClauseBuilder.d.ts +20 -0
- package/dist/queryGenerator/WhereClauseBuilder.d.ts.map +1 -0
- package/dist/queryGenerator/WhereClauseBuilder.js +63 -0
- package/dist/queryGenerator/WhereClauseBuilder.js.map +1 -0
- package/dist/queryGenerator/index.d.ts +10 -0
- package/dist/queryGenerator/index.d.ts.map +1 -0
- package/dist/queryGenerator/index.js +19 -0
- package/dist/queryGenerator/index.js.map +1 -0
- package/dist/queryGenerator.d.ts +61 -0
- package/dist/queryGenerator.d.ts.map +1 -0
- package/dist/queryGenerator.js +187 -0
- package/dist/queryGenerator.js.map +1 -0
- package/dist/tests/sqlOnFhir.test.d.ts +11 -0
- package/dist/tests/sqlOnFhir.test.d.ts.map +1 -0
- package/dist/tests/sqlOnFhir.test.js +24 -0
- package/dist/tests/sqlOnFhir.test.js.map +1 -0
- package/dist/tests/utils/database.d.ts +38 -0
- package/dist/tests/utils/database.d.ts.map +1 -0
- package/dist/tests/utils/database.js +258 -0
- package/dist/tests/utils/database.js.map +1 -0
- package/dist/tests/utils/generator.d.ts +58 -0
- package/dist/tests/utils/generator.d.ts.map +1 -0
- package/dist/tests/utils/generator.js +195 -0
- package/dist/tests/utils/generator.js.map +1 -0
- package/dist/tests/utils/reporter.d.ts +83 -0
- package/dist/tests/utils/reporter.d.ts.map +1 -0
- package/dist/tests/utils/reporter.js +245 -0
- package/dist/tests/utils/reporter.js.map +1 -0
- package/dist/tests/utils/sqlOnFhir.d.ts +33 -0
- package/dist/tests/utils/sqlOnFhir.d.ts.map +1 -0
- package/dist/tests/utils/sqlOnFhir.js +281 -0
- package/dist/tests/utils/sqlOnFhir.js.map +1 -0
- package/dist/tests/utils/testContext.d.ts +18 -0
- package/dist/tests/utils/testContext.d.ts.map +1 -0
- package/dist/tests/utils/testContext.js +25 -0
- package/dist/tests/utils/testContext.js.map +1 -0
- package/dist/tests/utils/types.d.ts +31 -0
- package/dist/tests/utils/types.d.ts.map +1 -0
- package/dist/tests/utils/types.js +9 -0
- package/dist/tests/utils/types.js.map +1 -0
- package/dist/types.d.ts +288 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Table management for NDJSON loader.
|
|
4
|
+
* Creates and manages the single fhir_resources table.
|
|
5
|
+
*
|
|
6
|
+
* @author John Grimes
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.tableExists = tableExists;
|
|
13
|
+
exports.createTable = createTable;
|
|
14
|
+
exports.truncateTable = truncateTable;
|
|
15
|
+
exports.ensureTable = ensureTable;
|
|
16
|
+
const mssql_1 = __importDefault(require("mssql"));
|
|
17
|
+
/**
|
|
18
|
+
* Check if a table exists in the database.
|
|
19
|
+
*
|
|
20
|
+
* @param pool - Database connection pool.
|
|
21
|
+
* @param schemaName - Schema name.
|
|
22
|
+
* @param tableName - Name of the table to check.
|
|
23
|
+
* @returns Promise that resolves to true if the table exists.
|
|
24
|
+
*/
|
|
25
|
+
async function tableExists(pool, schemaName, tableName) {
|
|
26
|
+
const result = await pool
|
|
27
|
+
.request()
|
|
28
|
+
.input("schemaName", mssql_1.default.NVarChar, schemaName)
|
|
29
|
+
.input("tableName", mssql_1.default.NVarChar, tableName).query(`
|
|
30
|
+
SELECT COUNT(*) as count
|
|
31
|
+
FROM INFORMATION_SCHEMA.TABLES
|
|
32
|
+
WHERE TABLE_SCHEMA = @schemaName AND TABLE_NAME = @tableName
|
|
33
|
+
`);
|
|
34
|
+
return result.recordset[0].count > 0;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create the fhir_resources table with an index on resource_type.
|
|
38
|
+
* Table schema: id (INT IDENTITY PRIMARY KEY), resource_type (NVARCHAR(64)), json (NVARCHAR(MAX))
|
|
39
|
+
*
|
|
40
|
+
* @param pool - Database connection pool.
|
|
41
|
+
* @param schemaName - Schema name.
|
|
42
|
+
* @param tableName - Name of the table to create.
|
|
43
|
+
*/
|
|
44
|
+
async function createTable(pool, schemaName, tableName) {
|
|
45
|
+
// Create the table.
|
|
46
|
+
await pool.request().query(`
|
|
47
|
+
CREATE TABLE [${schemaName}].[${tableName}] (
|
|
48
|
+
[id] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
|
|
49
|
+
[resource_type] NVARCHAR(64) NOT NULL,
|
|
50
|
+
[json] NVARCHAR(MAX) NOT NULL
|
|
51
|
+
)
|
|
52
|
+
`);
|
|
53
|
+
// Create an index on resource_type for efficient filtering by resource type.
|
|
54
|
+
await pool.request().query(`
|
|
55
|
+
CREATE INDEX [IX_${tableName}_resource_type]
|
|
56
|
+
ON [${schemaName}].[${tableName}] ([resource_type])
|
|
57
|
+
`);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Truncate a table (remove all rows).
|
|
61
|
+
*
|
|
62
|
+
* @param pool - Database connection pool.
|
|
63
|
+
* @param schemaName - Schema name.
|
|
64
|
+
* @param tableName - Name of the table to truncate.
|
|
65
|
+
*/
|
|
66
|
+
async function truncateTable(pool, schemaName, tableName) {
|
|
67
|
+
await pool.request().query(`TRUNCATE TABLE [${schemaName}].[${tableName}]`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Ensure the fhir_resources table exists, creating it if necessary.
|
|
71
|
+
*
|
|
72
|
+
* @param pool - Database connection pool.
|
|
73
|
+
* @param schemaName - Schema name.
|
|
74
|
+
* @param tableName - Name of the table.
|
|
75
|
+
* @param truncate - Whether to truncate the table if it exists.
|
|
76
|
+
*/
|
|
77
|
+
async function ensureTable(pool, schemaName, tableName, truncate = false) {
|
|
78
|
+
const exists = await tableExists(pool, schemaName, tableName);
|
|
79
|
+
if (exists) {
|
|
80
|
+
if (truncate) {
|
|
81
|
+
await truncateTable(pool, schemaName, tableName);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
await createTable(pool, schemaName, tableName);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/loader/tables.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;AAYH,kCAeC;AAUD,kCAmBC;AASD,sCAMC;AAUD,kCAeC;AA9FD,kDAAiD;AAEjD;;;;;;;GAOG;AACI,KAAK,UAAU,WAAW,CAC/B,IAAoB,EACpB,UAAkB,EAClB,SAAiB;IAEjB,MAAM,MAAM,GAAG,MAAM,IAAI;SACtB,OAAO,EAAE;SACT,KAAK,CAAC,YAAY,EAAE,eAAG,CAAC,QAAQ,EAAE,UAAU,CAAC;SAC7C,KAAK,CAAC,WAAW,EAAE,eAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,KAAK,CAAC;;;;KAIlD,CAAC,CAAC;IAEL,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,WAAW,CAC/B,IAAoB,EACpB,UAAkB,EAClB,SAAiB;IAEjB,oBAAoB;IACpB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC;oBACT,UAAU,MAAM,SAAS;;;;;GAK1C,CAAC,CAAC;IAEH,6EAA6E;IAC7E,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC;uBACN,SAAS;UACtB,UAAU,MAAM,SAAS;GAChC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,aAAa,CACjC,IAAoB,EACpB,UAAkB,EAClB,SAAiB;IAEjB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,mBAAmB,UAAU,MAAM,SAAS,GAAG,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;GAOG;AACI,KAAK,UAAU,WAAW,CAC/B,IAAoB,EACpB,UAAkB,EAClB,SAAiB,EACjB,WAAoB,KAAK;IAEzB,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAE9D,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACjD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the NDJSON loader.
|
|
3
|
+
*
|
|
4
|
+
* @author John Grimes
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Database connection configuration.
|
|
8
|
+
*/
|
|
9
|
+
export interface DatabaseConfig {
|
|
10
|
+
/** Database server hostname or IP address. */
|
|
11
|
+
host: string;
|
|
12
|
+
/** Database server port. */
|
|
13
|
+
port?: number;
|
|
14
|
+
/** Database username. */
|
|
15
|
+
user: string;
|
|
16
|
+
/** Database password. */
|
|
17
|
+
password: string;
|
|
18
|
+
/** Database name. */
|
|
19
|
+
database: string;
|
|
20
|
+
/** Whether to trust the server certificate. */
|
|
21
|
+
trustServerCertificate?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Discovered NDJSON file with metadata.
|
|
25
|
+
*/
|
|
26
|
+
export interface DiscoveredFile {
|
|
27
|
+
/** Full path to the file. */
|
|
28
|
+
path: string;
|
|
29
|
+
/** FHIR resource type extracted from filename. */
|
|
30
|
+
resourceType: string;
|
|
31
|
+
/** File size in bytes. */
|
|
32
|
+
size: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Options for the NDJSON loader.
|
|
36
|
+
*/
|
|
37
|
+
export interface LoaderOptions {
|
|
38
|
+
/** Directory containing NDJSON files. */
|
|
39
|
+
directory: string;
|
|
40
|
+
/** Database connection configuration. */
|
|
41
|
+
database: DatabaseConfig;
|
|
42
|
+
/** File naming pattern (default: {ResourceType}.ndjson). */
|
|
43
|
+
pattern?: string;
|
|
44
|
+
/** Filter to specific resource type. */
|
|
45
|
+
resourceType?: string;
|
|
46
|
+
/** Table name for storing resources (default: fhir_resources). */
|
|
47
|
+
tableName?: string;
|
|
48
|
+
/** Schema name (default: dbo). */
|
|
49
|
+
schemaName?: string;
|
|
50
|
+
/** Create table if it doesn't exist. */
|
|
51
|
+
createTable?: boolean;
|
|
52
|
+
/** Truncate table before loading. */
|
|
53
|
+
truncate?: boolean;
|
|
54
|
+
/** Number of rows per batch for bulk insert. */
|
|
55
|
+
batchSize?: number;
|
|
56
|
+
/** Number of files to process in parallel. */
|
|
57
|
+
parallel?: number;
|
|
58
|
+
/** Continue loading other files if one fails. */
|
|
59
|
+
continueOnError?: boolean;
|
|
60
|
+
/** Show what would be loaded without loading. */
|
|
61
|
+
dryRun?: boolean;
|
|
62
|
+
/** Enable verbose logging. */
|
|
63
|
+
verbose?: boolean;
|
|
64
|
+
/** Minimal output. */
|
|
65
|
+
quiet?: boolean;
|
|
66
|
+
/** Show progress bar. */
|
|
67
|
+
progress?: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Progress information for a file being loaded.
|
|
71
|
+
*/
|
|
72
|
+
export interface FileProgress {
|
|
73
|
+
/** File being processed. */
|
|
74
|
+
file: DiscoveredFile;
|
|
75
|
+
/** Number of rows loaded. */
|
|
76
|
+
rowsLoaded: number;
|
|
77
|
+
/** Number of rows that failed to load. */
|
|
78
|
+
rowsFailed: number;
|
|
79
|
+
/** Whether the file has completed loading. */
|
|
80
|
+
completed: boolean;
|
|
81
|
+
/** Error message if the file failed to load. */
|
|
82
|
+
error?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Overall progress for the loading operation.
|
|
86
|
+
*/
|
|
87
|
+
export interface LoaderProgress {
|
|
88
|
+
/** Total number of files to process. */
|
|
89
|
+
totalFiles: number;
|
|
90
|
+
/** Number of files completed. */
|
|
91
|
+
filesCompleted: number;
|
|
92
|
+
/** Total rows loaded across all files. */
|
|
93
|
+
totalRowsLoaded: number;
|
|
94
|
+
/** Total rows failed across all files. */
|
|
95
|
+
totalRowsFailed: number;
|
|
96
|
+
/** Progress for each file. */
|
|
97
|
+
fileProgress: Map<string, FileProgress>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Summary of the loading operation.
|
|
101
|
+
*/
|
|
102
|
+
export interface LoaderSummary {
|
|
103
|
+
/** Number of files successfully loaded. */
|
|
104
|
+
filesLoaded: number;
|
|
105
|
+
/** Number of files that failed to load. */
|
|
106
|
+
filesFailed: number;
|
|
107
|
+
/** Total rows loaded. */
|
|
108
|
+
rowsLoaded: number;
|
|
109
|
+
/** Total rows that failed to load. */
|
|
110
|
+
rowsFailed: number;
|
|
111
|
+
/** Duration in milliseconds. */
|
|
112
|
+
durationMs: number;
|
|
113
|
+
/** Errors encountered during loading. */
|
|
114
|
+
errors: Array<{
|
|
115
|
+
file: string;
|
|
116
|
+
error: string;
|
|
117
|
+
}>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Result of loading a single file.
|
|
121
|
+
*/
|
|
122
|
+
export interface FileLoadResult {
|
|
123
|
+
/** File that was loaded. */
|
|
124
|
+
file: DiscoveredFile;
|
|
125
|
+
/** Number of rows successfully loaded. */
|
|
126
|
+
rowsLoaded: number;
|
|
127
|
+
/** Number of rows that failed to load. */
|
|
128
|
+
rowsFailed: number;
|
|
129
|
+
/** Duration in milliseconds. */
|
|
130
|
+
durationMs: number;
|
|
131
|
+
/** Error message if the file failed to load. */
|
|
132
|
+
error?: string;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/loader/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/loader/types.ts"],"names":[],"mappings":";AAAA;;;;GAIG"}
|
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser for ViewDefinition JSON structures.
|
|
3
|
+
*/
|
|
4
|
+
import { TestSuite, ViewDefinition } from "./types.js";
|
|
5
|
+
export declare class ViewDefinitionParser {
|
|
6
|
+
/**
|
|
7
|
+
* Parse a ViewDefinition from JSON.
|
|
8
|
+
*/
|
|
9
|
+
static parseViewDefinition(json: string | object): ViewDefinition;
|
|
10
|
+
/**
|
|
11
|
+
* Parse a test suite from the sql-on-fhir-v2 format.
|
|
12
|
+
*/
|
|
13
|
+
static parseTestSuite(json: string | object): TestSuite;
|
|
14
|
+
/**
|
|
15
|
+
* Validate and narrow a ViewDefinition structure using type predicate.
|
|
16
|
+
*/
|
|
17
|
+
private static isValidViewDefinition;
|
|
18
|
+
/**
|
|
19
|
+
* Validate select element using type predicate.
|
|
20
|
+
*/
|
|
21
|
+
private static isValidSelect;
|
|
22
|
+
/**
|
|
23
|
+
* Validate select element has required structure.
|
|
24
|
+
*/
|
|
25
|
+
private static validateSelectStructure;
|
|
26
|
+
/**
|
|
27
|
+
* Validate forEach and forEachOrNull expressions.
|
|
28
|
+
*/
|
|
29
|
+
private static validateSelectExpressions;
|
|
30
|
+
/**
|
|
31
|
+
* Validate columns in a select element.
|
|
32
|
+
*/
|
|
33
|
+
private static validateSelectColumns;
|
|
34
|
+
/**
|
|
35
|
+
* Validate nested select elements.
|
|
36
|
+
*/
|
|
37
|
+
private static validateNestedSelects;
|
|
38
|
+
/**
|
|
39
|
+
* Validate unionAll branches.
|
|
40
|
+
*/
|
|
41
|
+
private static validateUnionAll;
|
|
42
|
+
/**
|
|
43
|
+
* Validate column using type predicate.
|
|
44
|
+
*/
|
|
45
|
+
private static isValidColumn;
|
|
46
|
+
/**
|
|
47
|
+
* Validate collection property constraints.
|
|
48
|
+
*/
|
|
49
|
+
private static validateCollectionConstraints;
|
|
50
|
+
/**
|
|
51
|
+
* Validate that all branches of a unionAll have the same columns in the same order.
|
|
52
|
+
*/
|
|
53
|
+
private static validateUnionAllColumns;
|
|
54
|
+
/**
|
|
55
|
+
* Extract column definitions from a select element.
|
|
56
|
+
* Handles direct columns, forEach columns, and nested select columns.
|
|
57
|
+
*/
|
|
58
|
+
private static extractColumnsFromSelect;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,SAAS,EAIT,cAAc,EAGf,MAAM,YAAY,CAAC;AAEpB,qBAAa,oBAAoB;IAC/B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc;IAWjE;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAUvD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IA8BpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAa5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAQtC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAUxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAWpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAWpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAY/B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAyB5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,6BAA6B;IAiC5C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;IA0CtC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,wBAAwB;CA+BxC"}
|
package/dist/parser.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Parser for ViewDefinition JSON structures.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ViewDefinitionParser = void 0;
|
|
7
|
+
class ViewDefinitionParser {
|
|
8
|
+
/**
|
|
9
|
+
* Parse a ViewDefinition from JSON.
|
|
10
|
+
*/
|
|
11
|
+
static parseViewDefinition(json) {
|
|
12
|
+
const data = typeof json === "string" ? JSON.parse(json) : json;
|
|
13
|
+
if (this.isValidViewDefinition(data)) {
|
|
14
|
+
return data;
|
|
15
|
+
}
|
|
16
|
+
throw new Error("Invalid ViewDefinition structure.");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse a test suite from the sql-on-fhir-v2 format.
|
|
20
|
+
*/
|
|
21
|
+
static parseTestSuite(json) {
|
|
22
|
+
const data = typeof json === "string" ? JSON.parse(json) : json;
|
|
23
|
+
if (!data.title || !data.resources || !data.tests) {
|
|
24
|
+
throw new Error("Invalid test suite format. Missing required fields.");
|
|
25
|
+
}
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate and narrow a ViewDefinition structure using type predicate.
|
|
30
|
+
*/
|
|
31
|
+
static isValidViewDefinition(data) {
|
|
32
|
+
if (!data.resource || typeof data.resource !== "string") {
|
|
33
|
+
throw new Error("ViewDefinition must specify a resource type.");
|
|
34
|
+
}
|
|
35
|
+
if (!data.select ||
|
|
36
|
+
!Array.isArray(data.select) ||
|
|
37
|
+
data.select.length === 0) {
|
|
38
|
+
throw new Error("ViewDefinition must have at least one select element.");
|
|
39
|
+
}
|
|
40
|
+
// Status is optional for test cases, but recommended for production use
|
|
41
|
+
// The SQL-on-FHIR spec requires status, but test cases may omit it
|
|
42
|
+
// Default to 'active' if not specified
|
|
43
|
+
data.status ??= "active";
|
|
44
|
+
// Validate select elements
|
|
45
|
+
for (const select of data.select) {
|
|
46
|
+
if (!this.isValidSelect(select)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validate select element using type predicate.
|
|
54
|
+
*/
|
|
55
|
+
static isValidSelect(select) {
|
|
56
|
+
this.validateSelectStructure(select);
|
|
57
|
+
this.validateSelectExpressions(select);
|
|
58
|
+
return (this.validateSelectColumns(select) &&
|
|
59
|
+
this.validateNestedSelects(select) &&
|
|
60
|
+
this.validateUnionAll(select));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validate select element has required structure.
|
|
64
|
+
*/
|
|
65
|
+
static validateSelectStructure(select) {
|
|
66
|
+
if (!select.column && !select.select && !select.unionAll) {
|
|
67
|
+
throw new Error("Select element must have columns, nested selects, or unionAll.");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Validate forEach and forEachOrNull expressions.
|
|
72
|
+
*/
|
|
73
|
+
static validateSelectExpressions(select) {
|
|
74
|
+
if (select.forEach && typeof select.forEach !== "string") {
|
|
75
|
+
throw new Error("forEach must be a string FHIRPath expression.");
|
|
76
|
+
}
|
|
77
|
+
if (select.forEachOrNull && typeof select.forEachOrNull !== "string") {
|
|
78
|
+
throw new Error("forEachOrNull must be a string FHIRPath expression.");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Validate columns in a select element.
|
|
83
|
+
*/
|
|
84
|
+
static validateSelectColumns(select) {
|
|
85
|
+
if (select.column) {
|
|
86
|
+
for (const column of select.column) {
|
|
87
|
+
if (!this.isValidColumn(column, select)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate nested select elements.
|
|
96
|
+
*/
|
|
97
|
+
static validateNestedSelects(select) {
|
|
98
|
+
if (select.select) {
|
|
99
|
+
for (const nestedSelect of select.select) {
|
|
100
|
+
if (!this.isValidSelect(nestedSelect)) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Validate unionAll branches.
|
|
109
|
+
*/
|
|
110
|
+
static validateUnionAll(select) {
|
|
111
|
+
if (select.unionAll) {
|
|
112
|
+
for (const unionSelect of select.unionAll) {
|
|
113
|
+
if (!this.isValidSelect(unionSelect)) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
this.validateUnionAllColumns(select.unionAll);
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Validate column using type predicate.
|
|
123
|
+
*/
|
|
124
|
+
static isValidColumn(column, selectContext) {
|
|
125
|
+
if (!column.name || typeof column.name !== "string") {
|
|
126
|
+
throw new Error("Column must have a valid name.");
|
|
127
|
+
}
|
|
128
|
+
if (!column.path || typeof column.path !== "string") {
|
|
129
|
+
throw new Error("Column must have a valid FHIRPath expression.");
|
|
130
|
+
}
|
|
131
|
+
// Validate column name is database-friendly
|
|
132
|
+
if (!/^[a-zA-Z_]\w*$/.test(column.name)) {
|
|
133
|
+
throw new Error(`Column name '${column.name}' is not database-friendly. Use alphanumeric and underscores only.`);
|
|
134
|
+
}
|
|
135
|
+
// Validate collection constraints
|
|
136
|
+
this.validateCollectionConstraints(column, selectContext);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Validate collection property constraints.
|
|
141
|
+
*/
|
|
142
|
+
static validateCollectionConstraints(column, selectContext) {
|
|
143
|
+
if (column.collection === false) {
|
|
144
|
+
// At this point, path has been validated to be a string in isValidColumn
|
|
145
|
+
const path = column.path;
|
|
146
|
+
// Known array fields in FHIR Patient that could return multiple values
|
|
147
|
+
const multiValuedPaths = [
|
|
148
|
+
"name.family",
|
|
149
|
+
"name.given",
|
|
150
|
+
"telecom.value",
|
|
151
|
+
"address.line",
|
|
152
|
+
"identifier.value",
|
|
153
|
+
"extension.value",
|
|
154
|
+
];
|
|
155
|
+
// Check if this path could return multiple values without forEach context
|
|
156
|
+
const isInForEachContext = selectContext && (selectContext.forEach ?? selectContext.forEachOrNull);
|
|
157
|
+
if (!isInForEachContext &&
|
|
158
|
+
multiValuedPaths.some((multiPath) => path.includes(multiPath))) {
|
|
159
|
+
throw new Error(`Path '${path}' can return multiple values. Use collection=true or place within a forEach context.`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Validate that all branches of a unionAll have the same columns in the same order.
|
|
165
|
+
*/
|
|
166
|
+
static validateUnionAllColumns(unionAllBranches) {
|
|
167
|
+
if (unionAllBranches.length < 2) {
|
|
168
|
+
return; // Nothing to validate
|
|
169
|
+
}
|
|
170
|
+
// Extract column definitions from each branch
|
|
171
|
+
const branchColumns = [];
|
|
172
|
+
for (const branch of unionAllBranches) {
|
|
173
|
+
const columns = this.extractColumnsFromSelect(branch);
|
|
174
|
+
branchColumns.push(columns);
|
|
175
|
+
}
|
|
176
|
+
// Compare first branch with all other branches
|
|
177
|
+
const firstBranch = branchColumns[0];
|
|
178
|
+
for (let i = 1; i < branchColumns.length; i++) {
|
|
179
|
+
const currentBranch = branchColumns[i];
|
|
180
|
+
// Check if column count matches
|
|
181
|
+
if (firstBranch.length !== currentBranch.length) {
|
|
182
|
+
throw new Error(`unionAll branches must have the same columns. ` +
|
|
183
|
+
`Branch 1 has ${firstBranch.length} columns, but branch ${i + 1} has ${currentBranch.length} columns.`);
|
|
184
|
+
}
|
|
185
|
+
// Check if column names and order match
|
|
186
|
+
for (let j = 0; j < firstBranch.length; j++) {
|
|
187
|
+
if (firstBranch[j].name !== currentBranch[j].name) {
|
|
188
|
+
throw new Error(`unionAll branches must have the same columns in the same order. ` +
|
|
189
|
+
`Column at position ${j + 1}: branch 1 has "${firstBranch[j].name}", ` +
|
|
190
|
+
`but branch ${i + 1} has "${currentBranch[j].name}".`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Extract column definitions from a select element.
|
|
197
|
+
* Handles direct columns, forEach columns, and nested select columns.
|
|
198
|
+
*/
|
|
199
|
+
static extractColumnsFromSelect(select) {
|
|
200
|
+
const columns = [];
|
|
201
|
+
// Direct columns
|
|
202
|
+
if (select.column) {
|
|
203
|
+
for (const column of select.column) {
|
|
204
|
+
columns.push({
|
|
205
|
+
name: column.name,
|
|
206
|
+
type: column.type,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Nested select columns
|
|
211
|
+
if (select.select) {
|
|
212
|
+
for (const nestedSelect of select.select) {
|
|
213
|
+
const nestedColumns = this.extractColumnsFromSelect(nestedSelect);
|
|
214
|
+
columns.push(...nestedColumns);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// UnionAll - take columns from first branch (all branches should be validated to match)
|
|
218
|
+
if (select.unionAll && select.unionAll.length > 0) {
|
|
219
|
+
const unionColumns = this.extractColumnsFromSelect(select.unionAll[0]);
|
|
220
|
+
columns.push(...unionColumns);
|
|
221
|
+
}
|
|
222
|
+
return columns;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.ViewDefinitionParser = ViewDefinitionParser;
|
|
226
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates SQL expressions for ViewDefinition columns.
|
|
3
|
+
*/
|
|
4
|
+
import { TranspilerContext } from "../fhirpath/transpiler.js";
|
|
5
|
+
import { ViewDefinitionColumn } from "../types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Handles generation of column expressions with type casting.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ColumnExpressionGenerator {
|
|
10
|
+
/**
|
|
11
|
+
* Generate SQL expression for a column.
|
|
12
|
+
*/
|
|
13
|
+
generateExpression(column: ViewDefinitionColumn, context: TranspilerContext): string;
|
|
14
|
+
/**
|
|
15
|
+
* Apply type casting to an expression.
|
|
16
|
+
*/
|
|
17
|
+
private applyTypeCasting;
|
|
18
|
+
/**
|
|
19
|
+
* Generate a CASE expression for boolean conversion.
|
|
20
|
+
* Handles both simple JSON_VALUE fields and boolean expressions.
|
|
21
|
+
*/
|
|
22
|
+
private generateBooleanCaseExpression;
|
|
23
|
+
/**
|
|
24
|
+
* Generate collection expression that returns an array.
|
|
25
|
+
*/
|
|
26
|
+
private generateCollectionExpression;
|
|
27
|
+
/**
|
|
28
|
+
* Build a JSON path expression for collection=true.
|
|
29
|
+
*/
|
|
30
|
+
private buildCollectionJsonPath;
|
|
31
|
+
/**
|
|
32
|
+
* Check if path is name.family.
|
|
33
|
+
*/
|
|
34
|
+
private isNameFamilyPath;
|
|
35
|
+
/**
|
|
36
|
+
* Check if path is name.given.
|
|
37
|
+
*/
|
|
38
|
+
private isNameGivenPath;
|
|
39
|
+
/**
|
|
40
|
+
* Build collection query for name.family path.
|
|
41
|
+
*/
|
|
42
|
+
private buildNameFamilyCollectionQuery;
|
|
43
|
+
/**
|
|
44
|
+
* Build collection query for name.given path.
|
|
45
|
+
*/
|
|
46
|
+
private buildNameGivenCollectionQuery;
|
|
47
|
+
/**
|
|
48
|
+
* Generate single value expression for collection=false.
|
|
49
|
+
*/
|
|
50
|
+
private generateSingleValueExpression;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=ColumnExpressionGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColumnExpressionGenerator.d.ts","sourceRoot":"","sources":["../../src/queryGenerator/ColumnExpressionGenerator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAc,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD;;GAEG;AACH,qBAAa,yBAAyB;IACpC;;OAEG;IACH,kBAAkB,CAChB,MAAM,EAAE,oBAAoB,EAC5B,OAAO,EAAE,iBAAiB,GACzB,MAAM;IA0BT;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;;OAGG;IACH,OAAO,CAAC,6BAA6B;IAkBrC;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAWpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAkB/B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAQxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAWtC;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAYrC;;OAEG;IACH,OAAO,CAAC,6BAA6B;CAMtC"}
|