flexdataset 0.4.1
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 +201 -0
- package/README.md +30 -0
- package/dist/src/cli.d.ts +9 -0
- package/dist/src/cli.js +179 -0
- package/dist/src/diagram/dag.d.ts +16 -0
- package/dist/src/diagram/dag.js +58 -0
- package/dist/src/diagram/er.d.ts +16 -0
- package/dist/src/diagram/er.js +62 -0
- package/dist/src/diagram/render.d.ts +16 -0
- package/dist/src/diagram/render.js +24 -0
- package/dist/src/iceberg.d.ts +85 -0
- package/dist/src/iceberg.js +221 -0
- package/dist/src/index.d.ts +18 -0
- package/dist/src/index.js +56 -0
- package/dist/src/loader.d.ts +26 -0
- package/dist/src/loader.js +239 -0
- package/dist/src/model.d.ts +104 -0
- package/dist/src/model.js +26 -0
- package/dist/src/schema/schema.schema.json +27 -0
- package/dist/src/schema/table.schema.json +128 -0
- package/dist/src/structural.d.ts +31 -0
- package/dist/src/structural.js +54 -0
- package/dist/src/table-type.d.ts +115 -0
- package/dist/src/table-type.js +275 -0
- package/dist/src/table-types/hive-parquet.d.ts +29 -0
- package/dist/src/table-types/hive-parquet.js +70 -0
- package/dist/src/table-types/iceberg-parquet.d.ts +41 -0
- package/dist/src/table-types/iceberg-parquet.js +103 -0
- package/dist/src/table-types/postgres-18.d.ts +25 -0
- package/dist/src/table-types/postgres-18.js +44 -0
- package/dist/src/table-types/registry.d.ts +13 -0
- package/dist/src/table-types/registry.js +36 -0
- package/dist/src/types.d.ts +11 -0
- package/dist/src/types.js +182 -0
- package/dist/src/validate.d.ts +13 -0
- package/dist/src/validate.js +30 -0
- package/dist/src/world.d.ts +39 -0
- package/dist/src/world.js +82 -0
- package/package.json +69 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Iceberg (parquet) table type.
|
|
4
|
+
*
|
|
5
|
+
* Iceberg partitions are transforms applied to a data column, so duplicate
|
|
6
|
+
* detection keys on the (source column, normalized transform) pair — `year(ts)`
|
|
7
|
+
* and `month(ts)` are distinct, while `day` and `DAY` collapse.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.IcebergParquetTable = void 0;
|
|
11
|
+
const table_type_1 = require("../table-type");
|
|
12
|
+
const iceberg_1 = require("../iceberg");
|
|
13
|
+
/** Iceberg (parquet) table. */
|
|
14
|
+
class IcebergParquetTable extends table_type_1.TableTypeBase {
|
|
15
|
+
/**
|
|
16
|
+
* Validate a column type against the Iceberg v0 type registry.
|
|
17
|
+
*
|
|
18
|
+
* @param type Type string from a column definition.
|
|
19
|
+
* @returns True when the type is a valid Iceberg type.
|
|
20
|
+
*/
|
|
21
|
+
isValidColumnType(type) {
|
|
22
|
+
return (0, iceberg_1.isValidIcebergType)(type);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Iceberg partition rules.
|
|
26
|
+
*
|
|
27
|
+
* Emits: `NO_DUPLICATE_PARTITIONS` (keyed by `${name} ${transformKind}:${param}`,
|
|
28
|
+
* falling back to a lowercased trim of the raw transform when it doesn't
|
|
29
|
+
* parse, so whitespace / case variants of the same transform collapse),
|
|
30
|
+
* `ICEBERG_TRANSFORM_SOURCE_EXISTS`, `ICEBERG_TRANSFORM_VALID`, and
|
|
31
|
+
* `ICEBERG_TRANSFORM_SOURCE_TYPE_LEGAL`.
|
|
32
|
+
*
|
|
33
|
+
* @returns Every partition-related violation.
|
|
34
|
+
*/
|
|
35
|
+
partitionViolations() {
|
|
36
|
+
const violations = [];
|
|
37
|
+
const { partitions, } = this.definition;
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
partitions.forEach((partition, index) => {
|
|
40
|
+
const key = this.partitionKey(partition);
|
|
41
|
+
if (seen.has(key)) {
|
|
42
|
+
violations.push(this.violation({
|
|
43
|
+
level: 'error',
|
|
44
|
+
code: 'NO_DUPLICATE_PARTITIONS',
|
|
45
|
+
field: `partitions[${index}]`,
|
|
46
|
+
message: `duplicate partition: "${partition.name}" with transform "${partition.type}"`,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
seen.add(key);
|
|
50
|
+
});
|
|
51
|
+
partitions.forEach((partition, index) => {
|
|
52
|
+
const sourceColumn = this.definition.columns.find((column) => column.name === partition.name);
|
|
53
|
+
if (sourceColumn === undefined) {
|
|
54
|
+
violations.push(this.violation({
|
|
55
|
+
level: 'error',
|
|
56
|
+
code: 'ICEBERG_TRANSFORM_SOURCE_EXISTS',
|
|
57
|
+
field: `partitions[${index}].name`,
|
|
58
|
+
message: `Iceberg partition source column "${partition.name}" is not defined in columns`,
|
|
59
|
+
}));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const transform = (0, iceberg_1.parseIcebergTransform)(partition.type);
|
|
63
|
+
if (transform === null) {
|
|
64
|
+
violations.push(this.violation({
|
|
65
|
+
level: 'error',
|
|
66
|
+
code: 'ICEBERG_TRANSFORM_VALID',
|
|
67
|
+
field: `partitions[${index}].type`,
|
|
68
|
+
message: `"${partition.type}" is not a valid Iceberg partition transform`,
|
|
69
|
+
}));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const sourceType = (0, iceberg_1.parseIcebergType)(sourceColumn.type);
|
|
73
|
+
if (sourceType !== null && !(0, iceberg_1.transformLegalOnType)(transform, sourceType)) {
|
|
74
|
+
violations.push(this.violation({
|
|
75
|
+
level: 'error',
|
|
76
|
+
code: 'ICEBERG_TRANSFORM_SOURCE_TYPE_LEGAL',
|
|
77
|
+
field: `partitions[${index}].type`,
|
|
78
|
+
message: `transform "${partition.type}" is not legal on `
|
|
79
|
+
+ `column "${partition.name}" of type "${sourceColumn.type}"`,
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return violations;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Normalize a partition into its identity key. When the transform parses,
|
|
87
|
+
* collapse on `${kind}:${param}` so `day` and `DAY`, `bucket[16]` and
|
|
88
|
+
* `bucket[ 16 ]` are the same. When the transform doesn't parse, the
|
|
89
|
+
* lowercased trim of the raw string is the best identity we have.
|
|
90
|
+
*
|
|
91
|
+
* @param partition Partition to key.
|
|
92
|
+
* @returns The identity string for duplicate detection.
|
|
93
|
+
*/
|
|
94
|
+
partitionKey(partition) {
|
|
95
|
+
const transform = (0, iceberg_1.parseIcebergTransform)(partition.type);
|
|
96
|
+
const normalizedTransform = transform
|
|
97
|
+
? `${transform.kind}:${transform.param ?? ''}`
|
|
98
|
+
: partition.type.trim().toLowerCase();
|
|
99
|
+
return `${partition.name} ${normalizedTransform}`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.IcebergParquetTable = IcebergParquetTable;
|
|
103
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWNlYmVyZy1wYXJxdWV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RhYmxlLXR5cGVzL2ljZWJlcmctcGFycXVldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7QUFNSCw4Q0FFdUI7QUFDdkIsd0NBS29CO0FBRXBCLCtCQUErQjtBQUMvQixNQUFhLG1CQUFvQixTQUFRLDBCQUFhO0lBQ2xEOzs7OztPQUtHO0lBQ0ksaUJBQWlCLENBQUMsSUFBWTtRQUNqQyxPQUFPLElBQUEsNEJBQWtCLEVBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSSxtQkFBbUI7UUFDdEIsTUFBTSxVQUFVLEdBQWdCLEVBQUUsQ0FBQztRQUNuQyxNQUFNLEVBQ0YsVUFBVSxHQUNiLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztRQUVwQixNQUFNLElBQUksR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQy9CLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDcEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN6QyxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDaEIsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO29CQUMzQixLQUFLLEVBQUUsT0FBTztvQkFDZCxJQUFJLEVBQUUseUJBQXlCO29CQUMvQixLQUFLLEVBQUUsY0FBYyxLQUFLLEdBQUc7b0JBQzdCLE9BQU8sRUFBRSx5QkFBeUIsU0FBUyxDQUFDLElBQUkscUJBQXFCLFNBQVMsQ0FBQyxJQUFJLEdBQUc7aUJBQ3pGLENBQUMsQ0FBQyxDQUFDO1lBQ1IsQ0FBQztZQUNELElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbEIsQ0FBQyxDQUFDLENBQUM7UUFFSCxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsU0FBUyxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3BDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUYsSUFBSSxZQUFZLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQzdCLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDM0IsS0FBSyxFQUFFLE9BQU87b0JBQ2QsSUFBSSxFQUFFLGlDQUFpQztvQkFDdkMsS0FBSyxFQUFFLGNBQWMsS0FBSyxRQUFRO29CQUNsQyxPQUFPLEVBQUUsb0NBQW9DLFNBQVMsQ0FBQyxJQUFJLDZCQUE2QjtpQkFDM0YsQ0FBQyxDQUFDLENBQUM7Z0JBQ0osT0FBTztZQUNYLENBQUM7WUFDRCxNQUFNLFNBQVMsR0FBRyxJQUFBLCtCQUFxQixFQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN4RCxJQUFJLFNBQVMsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDckIsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO29CQUMzQixLQUFLLEVBQUUsT0FBTztvQkFDZCxJQUFJLEVBQUUseUJBQXlCO29CQUMvQixLQUFLLEVBQUUsY0FBYyxLQUFLLFFBQVE7b0JBQ2xDLE9BQU8sRUFBRSxJQUFJLFNBQVMsQ0FBQyxJQUFJLDhDQUE4QztpQkFDNUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ0osT0FBTztZQUNYLENBQUM7WUFDRCxNQUFNLFVBQVUsR0FBRyxJQUFBLDBCQUFnQixFQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN2RCxJQUFJLFVBQVUsS0FBSyxJQUFJLElBQUksQ0FBQyxJQUFBLDhCQUFvQixFQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDO2dCQUN0RSxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQzNCLEtBQUssRUFBRSxPQUFPO29CQUNkLElBQUksRUFBRSxxQ0FBcUM7b0JBQzNDLEtBQUssRUFBRSxjQUFjLEtBQUssUUFBUTtvQkFDbEMsT0FBTyxFQUFFLGNBQWMsU0FBUyxDQUFDLElBQUksb0JBQW9COzBCQUNuRCxXQUFXLFNBQVMsQ0FBQyxJQUFJLGNBQWMsWUFBWSxDQUFDLElBQUksR0FBRztpQkFDcEUsQ0FBQyxDQUFDLENBQUM7WUFDUixDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLFVBQVUsQ0FBQztJQUN0QixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSyxZQUFZLENBQUMsU0FBb0I7UUFDckMsTUFBTSxTQUFTLEdBQUcsSUFBQSwrQkFBcUIsRUFBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEQsTUFBTSxtQkFBbUIsR0FBRyxTQUFTO1lBQ2pDLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxJQUFJLElBQUksU0FBUyxDQUFDLEtBQUssSUFBSSxFQUFFLEVBQUU7WUFDOUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDMUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxJQUFJLElBQUksbUJBQW1CLEVBQUUsQ0FBQztJQUN0RCxDQUFDO0NBQ0o7QUE5RkQsa0RBOEZDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBJY2ViZXJnIChwYXJxdWV0KSB0YWJsZSB0eXBlLlxuICpcbiAqIEljZWJlcmcgcGFydGl0aW9ucyBhcmUgdHJhbnNmb3JtcyBhcHBsaWVkIHRvIGEgZGF0YSBjb2x1bW4sIHNvIGR1cGxpY2F0ZVxuICogZGV0ZWN0aW9uIGtleXMgb24gdGhlIChzb3VyY2UgY29sdW1uLCBub3JtYWxpemVkIHRyYW5zZm9ybSkgcGFpciDigJQgYHllYXIodHMpYFxuICogYW5kIGBtb250aCh0cylgIGFyZSBkaXN0aW5jdCwgd2hpbGUgYGRheWAgYW5kIGBEQVlgIGNvbGxhcHNlLlxuICovXG5cbmltcG9ydCB7XG4gICAgUGFydGl0aW9uLFxuICAgIFZpb2xhdGlvbixcbn0gZnJvbSAnLi4vbW9kZWwnO1xuaW1wb3J0IHtcbiAgICBUYWJsZVR5cGVCYXNlLFxufSBmcm9tICcuLi90YWJsZS10eXBlJztcbmltcG9ydCB7XG4gICAgaXNWYWxpZEljZWJlcmdUeXBlLFxuICAgIHBhcnNlSWNlYmVyZ1RyYW5zZm9ybSxcbiAgICBwYXJzZUljZWJlcmdUeXBlLFxuICAgIHRyYW5zZm9ybUxlZ2FsT25UeXBlLFxufSBmcm9tICcuLi9pY2ViZXJnJztcblxuLyoqIEljZWJlcmcgKHBhcnF1ZXQpIHRhYmxlLiAqL1xuZXhwb3J0IGNsYXNzIEljZWJlcmdQYXJxdWV0VGFibGUgZXh0ZW5kcyBUYWJsZVR5cGVCYXNlIHtcbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZSBhIGNvbHVtbiB0eXBlIGFnYWluc3QgdGhlIEljZWJlcmcgdjAgdHlwZSByZWdpc3RyeS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0eXBlIFR5cGUgc3RyaW5nIGZyb20gYSBjb2x1bW4gZGVmaW5pdGlvbi5cbiAgICAgKiBAcmV0dXJucyBUcnVlIHdoZW4gdGhlIHR5cGUgaXMgYSB2YWxpZCBJY2ViZXJnIHR5cGUuXG4gICAgICovXG4gICAgcHVibGljIGlzVmFsaWRDb2x1bW5UeXBlKHR5cGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gaXNWYWxpZEljZWJlcmdUeXBlKHR5cGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEljZWJlcmcgcGFydGl0aW9uIHJ1bGVzLlxuICAgICAqXG4gICAgICogRW1pdHM6IGBOT19EVVBMSUNBVEVfUEFSVElUSU9OU2AgKGtleWVkIGJ5IGAke25hbWV9ICR7dHJhbnNmb3JtS2luZH06JHtwYXJhbX1gLFxuICAgICAqIGZhbGxpbmcgYmFjayB0byBhIGxvd2VyY2FzZWQgdHJpbSBvZiB0aGUgcmF3IHRyYW5zZm9ybSB3aGVuIGl0IGRvZXNuJ3RcbiAgICAgKiBwYXJzZSwgc28gd2hpdGVzcGFjZSAvIGNhc2UgdmFyaWFudHMgb2YgdGhlIHNhbWUgdHJhbnNmb3JtIGNvbGxhcHNlKSxcbiAgICAgKiBgSUNFQkVSR19UUkFOU0ZPUk1fU09VUkNFX0VYSVNUU2AsIGBJQ0VCRVJHX1RSQU5TRk9STV9WQUxJRGAsIGFuZFxuICAgICAqIGBJQ0VCRVJHX1RSQU5TRk9STV9TT1VSQ0VfVFlQRV9MRUdBTGAuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBFdmVyeSBwYXJ0aXRpb24tcmVsYXRlZCB2aW9sYXRpb24uXG4gICAgICovXG4gICAgcHVibGljIHBhcnRpdGlvblZpb2xhdGlvbnMoKTogVmlvbGF0aW9uW10ge1xuICAgICAgICBjb25zdCB2aW9sYXRpb25zOiBWaW9sYXRpb25bXSA9IFtdO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICBwYXJ0aXRpb25zLFxuICAgICAgICB9ID0gdGhpcy5kZWZpbml0aW9uO1xuXG4gICAgICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgICAgcGFydGl0aW9ucy5mb3JFYWNoKChwYXJ0aXRpb24sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBrZXkgPSB0aGlzLnBhcnRpdGlvbktleShwYXJ0aXRpb24pO1xuICAgICAgICAgICAgaWYgKHNlZW4uaGFzKGtleSkpIHtcbiAgICAgICAgICAgICAgICB2aW9sYXRpb25zLnB1c2godGhpcy52aW9sYXRpb24oe1xuICAgICAgICAgICAgICAgICAgICBsZXZlbDogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgY29kZTogJ05PX0RVUExJQ0FURV9QQVJUSVRJT05TJyxcbiAgICAgICAgICAgICAgICAgICAgZmllbGQ6IGBwYXJ0aXRpb25zWyR7aW5kZXh9XWAsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBkdXBsaWNhdGUgcGFydGl0aW9uOiBcIiR7cGFydGl0aW9uLm5hbWV9XCIgd2l0aCB0cmFuc2Zvcm0gXCIke3BhcnRpdGlvbi50eXBlfVwiYCxcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWVuLmFkZChrZXkpO1xuICAgICAgICB9KTtcblxuICAgICAgICBwYXJ0aXRpb25zLmZvckVhY2goKHBhcnRpdGlvbiwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZUNvbHVtbiA9IHRoaXMuZGVmaW5pdGlvbi5jb2x1bW5zLmZpbmQoKGNvbHVtbikgPT4gY29sdW1uLm5hbWUgPT09IHBhcnRpdGlvbi5uYW1lKTtcbiAgICAgICAgICAgIGlmIChzb3VyY2VDb2x1bW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnSUNFQkVSR19UUkFOU0ZPUk1fU09VUkNFX0VYSVNUUycsXG4gICAgICAgICAgICAgICAgICAgIGZpZWxkOiBgcGFydGl0aW9uc1ske2luZGV4fV0ubmFtZWAsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBJY2ViZXJnIHBhcnRpdGlvbiBzb3VyY2UgY29sdW1uIFwiJHtwYXJ0aXRpb24ubmFtZX1cIiBpcyBub3QgZGVmaW5lZCBpbiBjb2x1bW5zYCxcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdHJhbnNmb3JtID0gcGFyc2VJY2ViZXJnVHJhbnNmb3JtKHBhcnRpdGlvbi50eXBlKTtcbiAgICAgICAgICAgIGlmICh0cmFuc2Zvcm0gPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB2aW9sYXRpb25zLnB1c2godGhpcy52aW9sYXRpb24oe1xuICAgICAgICAgICAgICAgICAgICBsZXZlbDogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgY29kZTogJ0lDRUJFUkdfVFJBTlNGT1JNX1ZBTElEJyxcbiAgICAgICAgICAgICAgICAgICAgZmllbGQ6IGBwYXJ0aXRpb25zWyR7aW5kZXh9XS50eXBlYCxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYFwiJHtwYXJ0aXRpb24udHlwZX1cIiBpcyBub3QgYSB2YWxpZCBJY2ViZXJnIHBhcnRpdGlvbiB0cmFuc2Zvcm1gLFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBzb3VyY2VUeXBlID0gcGFyc2VJY2ViZXJnVHlwZShzb3VyY2VDb2x1bW4udHlwZSk7XG4gICAgICAgICAgICBpZiAoc291cmNlVHlwZSAhPT0gbnVsbCAmJiAhdHJhbnNmb3JtTGVnYWxPblR5cGUodHJhbnNmb3JtLCBzb3VyY2VUeXBlKSkge1xuICAgICAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnSUNFQkVSR19UUkFOU0ZPUk1fU09VUkNFX1RZUEVfTEVHQUwnLFxuICAgICAgICAgICAgICAgICAgICBmaWVsZDogYHBhcnRpdGlvbnNbJHtpbmRleH1dLnR5cGVgLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgdHJhbnNmb3JtIFwiJHtwYXJ0aXRpb24udHlwZX1cIiBpcyBub3QgbGVnYWwgb24gYFxuICAgICAgICAgICAgICAgICAgICAgICAgKyBgY29sdW1uIFwiJHtwYXJ0aXRpb24ubmFtZX1cIiBvZiB0eXBlIFwiJHtzb3VyY2VDb2x1bW4udHlwZX1cImAsXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdmlvbGF0aW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBOb3JtYWxpemUgYSBwYXJ0aXRpb24gaW50byBpdHMgaWRlbnRpdHkga2V5LiBXaGVuIHRoZSB0cmFuc2Zvcm0gcGFyc2VzLFxuICAgICAqIGNvbGxhcHNlIG9uIGAke2tpbmR9OiR7cGFyYW19YCBzbyBgZGF5YCBhbmQgYERBWWAsIGBidWNrZXRbMTZdYCBhbmRcbiAgICAgKiBgYnVja2V0WyAxNiBdYCBhcmUgdGhlIHNhbWUuIFdoZW4gdGhlIHRyYW5zZm9ybSBkb2Vzbid0IHBhcnNlLCB0aGVcbiAgICAgKiBsb3dlcmNhc2VkIHRyaW0gb2YgdGhlIHJhdyBzdHJpbmcgaXMgdGhlIGJlc3QgaWRlbnRpdHkgd2UgaGF2ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwYXJ0aXRpb24gUGFydGl0aW9uIHRvIGtleS5cbiAgICAgKiBAcmV0dXJucyBUaGUgaWRlbnRpdHkgc3RyaW5nIGZvciBkdXBsaWNhdGUgZGV0ZWN0aW9uLlxuICAgICAqL1xuICAgIHByaXZhdGUgcGFydGl0aW9uS2V5KHBhcnRpdGlvbjogUGFydGl0aW9uKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtID0gcGFyc2VJY2ViZXJnVHJhbnNmb3JtKHBhcnRpdGlvbi50eXBlKTtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFRyYW5zZm9ybSA9IHRyYW5zZm9ybVxuICAgICAgICAgICAgPyBgJHt0cmFuc2Zvcm0ua2luZH06JHt0cmFuc2Zvcm0ucGFyYW0gPz8gJyd9YFxuICAgICAgICAgICAgOiBwYXJ0aXRpb24udHlwZS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIGAke3BhcnRpdGlvbi5uYW1lfSAke25vcm1hbGl6ZWRUcmFuc2Zvcm19YDtcbiAgICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postgres 18 table type.
|
|
3
|
+
*
|
|
4
|
+
* Postgres partitioning is deferred to a later FDD version, so any partition
|
|
5
|
+
* entry is an error.
|
|
6
|
+
*/
|
|
7
|
+
import { Violation } from '../model';
|
|
8
|
+
import { TableTypeBase } from '../table-type';
|
|
9
|
+
/** Postgres 18 table. */
|
|
10
|
+
export declare class Postgres18Table extends TableTypeBase {
|
|
11
|
+
/**
|
|
12
|
+
* Validate a column type against the Postgres type registry.
|
|
13
|
+
*
|
|
14
|
+
* @param type Type string from a column definition.
|
|
15
|
+
* @returns True when the type is a valid Postgres 18 type.
|
|
16
|
+
*/
|
|
17
|
+
isValidColumnType(type: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Postgres has no partitions in v0; emit `PARTITIONS_ALLOWED_FOR_TYPE`
|
|
20
|
+
* once when any partition entry is present.
|
|
21
|
+
*
|
|
22
|
+
* @returns The single partition violation when partitions are declared, otherwise empty.
|
|
23
|
+
*/
|
|
24
|
+
partitionViolations(): Violation[];
|
|
25
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Postgres 18 table type.
|
|
4
|
+
*
|
|
5
|
+
* Postgres partitioning is deferred to a later FDD version, so any partition
|
|
6
|
+
* entry is an error.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.Postgres18Table = void 0;
|
|
10
|
+
const table_type_1 = require("../table-type");
|
|
11
|
+
const types_1 = require("../types");
|
|
12
|
+
/** Postgres 18 table. */
|
|
13
|
+
class Postgres18Table extends table_type_1.TableTypeBase {
|
|
14
|
+
/**
|
|
15
|
+
* Validate a column type against the Postgres type registry.
|
|
16
|
+
*
|
|
17
|
+
* @param type Type string from a column definition.
|
|
18
|
+
* @returns True when the type is a valid Postgres 18 type.
|
|
19
|
+
*/
|
|
20
|
+
isValidColumnType(type) {
|
|
21
|
+
return (0, types_1.isValidPostgresType)(type);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Postgres has no partitions in v0; emit `PARTITIONS_ALLOWED_FOR_TYPE`
|
|
25
|
+
* once when any partition entry is present.
|
|
26
|
+
*
|
|
27
|
+
* @returns The single partition violation when partitions are declared, otherwise empty.
|
|
28
|
+
*/
|
|
29
|
+
partitionViolations() {
|
|
30
|
+
if (this.definition.partitions.length === 0) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
return [
|
|
34
|
+
this.violation({
|
|
35
|
+
level: 'error',
|
|
36
|
+
code: 'PARTITIONS_ALLOWED_FOR_TYPE',
|
|
37
|
+
field: 'partitions',
|
|
38
|
+
message: 'partitions are not supported for postgres_18 in v0',
|
|
39
|
+
}),
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.Postgres18Table = Postgres18Table;
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zdGdyZXMtMTguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGFibGUtdHlwZXMvcG9zdGdyZXMtMTgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7OztHQUtHOzs7QUFLSCw4Q0FFdUI7QUFDdkIsb0NBRWtCO0FBRWxCLHlCQUF5QjtBQUN6QixNQUFhLGVBQWdCLFNBQVEsMEJBQWE7SUFDOUM7Ozs7O09BS0c7SUFDSSxpQkFBaUIsQ0FBQyxJQUFZO1FBQ2pDLE9BQU8sSUFBQSwyQkFBbUIsRUFBQyxJQUFJLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxtQkFBbUI7UUFDdEIsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDMUMsT0FBTyxFQUFFLENBQUM7UUFDZCxDQUFDO1FBQ0QsT0FBTztZQUNILElBQUksQ0FBQyxTQUFTLENBQUM7Z0JBQ1gsS0FBSyxFQUFFLE9BQU87Z0JBQ2QsSUFBSSxFQUFFLDZCQUE2QjtnQkFDbkMsS0FBSyxFQUFFLFlBQVk7Z0JBQ25CLE9BQU8sRUFBRSxvREFBb0Q7YUFDaEUsQ0FBQztTQUNMLENBQUM7SUFDTixDQUFDO0NBQ0o7QUE5QkQsMENBOEJDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQb3N0Z3JlcyAxOCB0YWJsZSB0eXBlLlxuICpcbiAqIFBvc3RncmVzIHBhcnRpdGlvbmluZyBpcyBkZWZlcnJlZCB0byBhIGxhdGVyIEZERCB2ZXJzaW9uLCBzbyBhbnkgcGFydGl0aW9uXG4gKiBlbnRyeSBpcyBhbiBlcnJvci5cbiAqL1xuXG5pbXBvcnQge1xuICAgIFZpb2xhdGlvbixcbn0gZnJvbSAnLi4vbW9kZWwnO1xuaW1wb3J0IHtcbiAgICBUYWJsZVR5cGVCYXNlLFxufSBmcm9tICcuLi90YWJsZS10eXBlJztcbmltcG9ydCB7XG4gICAgaXNWYWxpZFBvc3RncmVzVHlwZSxcbn0gZnJvbSAnLi4vdHlwZXMnO1xuXG4vKiogUG9zdGdyZXMgMTggdGFibGUuICovXG5leHBvcnQgY2xhc3MgUG9zdGdyZXMxOFRhYmxlIGV4dGVuZHMgVGFibGVUeXBlQmFzZSB7XG4gICAgLyoqXG4gICAgICogVmFsaWRhdGUgYSBjb2x1bW4gdHlwZSBhZ2FpbnN0IHRoZSBQb3N0Z3JlcyB0eXBlIHJlZ2lzdHJ5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHR5cGUgVHlwZSBzdHJpbmcgZnJvbSBhIGNvbHVtbiBkZWZpbml0aW9uLlxuICAgICAqIEByZXR1cm5zIFRydWUgd2hlbiB0aGUgdHlwZSBpcyBhIHZhbGlkIFBvc3RncmVzIDE4IHR5cGUuXG4gICAgICovXG4gICAgcHVibGljIGlzVmFsaWRDb2x1bW5UeXBlKHR5cGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gaXNWYWxpZFBvc3RncmVzVHlwZSh0eXBlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQb3N0Z3JlcyBoYXMgbm8gcGFydGl0aW9ucyBpbiB2MDsgZW1pdCBgUEFSVElUSU9OU19BTExPV0VEX0ZPUl9UWVBFYFxuICAgICAqIG9uY2Ugd2hlbiBhbnkgcGFydGl0aW9uIGVudHJ5IGlzIHByZXNlbnQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgc2luZ2xlIHBhcnRpdGlvbiB2aW9sYXRpb24gd2hlbiBwYXJ0aXRpb25zIGFyZSBkZWNsYXJlZCwgb3RoZXJ3aXNlIGVtcHR5LlxuICAgICAqL1xuICAgIHB1YmxpYyBwYXJ0aXRpb25WaW9sYXRpb25zKCk6IFZpb2xhdGlvbltdIHtcbiAgICAgICAgaWYgKHRoaXMuZGVmaW5pdGlvbi5wYXJ0aXRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgbGV2ZWw6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgY29kZTogJ1BBUlRJVElPTlNfQUxMT1dFRF9GT1JfVFlQRScsXG4gICAgICAgICAgICAgICAgZmllbGQ6ICdwYXJ0aXRpb25zJyxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiAncGFydGl0aW9ucyBhcmUgbm90IHN1cHBvcnRlZCBmb3IgcG9zdGdyZXNfMTggaW4gdjAnLFxuICAgICAgICAgICAgfSksXG4gICAgICAgIF07XG4gICAgfVxufVxuIl19
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry mapping the `tableType` string to the concrete `TableTypeBase`
|
|
3
|
+
* subclass that implements it. Adding a new engine is a matter of writing a
|
|
4
|
+
* subclass and adding one entry here.
|
|
5
|
+
*/
|
|
6
|
+
import { TableTypeBase, TableTypeFields } from '../table-type';
|
|
7
|
+
/**
|
|
8
|
+
* Build the concrete `TableTypeBase` subclass for the given fields.
|
|
9
|
+
*
|
|
10
|
+
* @param fields The normalized table fields.
|
|
11
|
+
* @returns A concrete table instance for the engine named by `fields.definition.tableType`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createTableType(fields: TableTypeFields): TableTypeBase;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Registry mapping the `tableType` string to the concrete `TableTypeBase`
|
|
4
|
+
* subclass that implements it. Adding a new engine is a matter of writing a
|
|
5
|
+
* subclass and adding one entry here.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createTableType = createTableType;
|
|
9
|
+
const model_1 = require("../model");
|
|
10
|
+
const hive_parquet_1 = require("./hive-parquet");
|
|
11
|
+
const iceberg_parquet_1 = require("./iceberg-parquet");
|
|
12
|
+
const postgres_18_1 = require("./postgres-18");
|
|
13
|
+
/// Exhaustive map: every value of the `TableType` enum has a concrete subclass.
|
|
14
|
+
const REGISTRY = {
|
|
15
|
+
[model_1.TableType.HIVE_PARQUET]: hive_parquet_1.HiveParquetTable,
|
|
16
|
+
[model_1.TableType.ICEBERG_PARQUET]: iceberg_parquet_1.IcebergParquetTable,
|
|
17
|
+
[model_1.TableType.POSTGRES_18]: postgres_18_1.Postgres18Table,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Build the concrete `TableTypeBase` subclass for the given fields.
|
|
21
|
+
*
|
|
22
|
+
* @param fields The normalized table fields.
|
|
23
|
+
* @returns A concrete table instance for the engine named by `fields.definition.tableType`.
|
|
24
|
+
*/
|
|
25
|
+
function createTableType(fields) {
|
|
26
|
+
const tableType = fields.definition.tableType;
|
|
27
|
+
/// An unrecognized `tableType` only occurs when Layer 1 already flagged the
|
|
28
|
+
/// file: such tables are skipped by intra-table rules and skipped as FK
|
|
29
|
+
/// targets, so the choice here is purely for cross-file *resolution* (the
|
|
30
|
+
/// instance still needs to land in `world.tables` so dependsOn / FK source
|
|
31
|
+
/// lookups don't pretend the file is missing). `HiveParquetTable` is the
|
|
32
|
+
/// resolution-only fallback.
|
|
33
|
+
const Constructor = REGISTRY[tableType] ?? hive_parquet_1.HiveParquetTable;
|
|
34
|
+
return new Constructor(fields);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGFibGUtdHlwZXMvcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7O0dBSUc7O0FBbUNILDBDQVVDO0FBM0NELG9DQUVrQjtBQUtsQixpREFFd0I7QUFDeEIsdURBRTJCO0FBQzNCLCtDQUV1QjtBQUt2QixnRkFBZ0Y7QUFDaEYsTUFBTSxRQUFRLEdBQTRDO0lBQ3RELENBQUMsaUJBQVMsQ0FBQyxZQUFZLENBQUMsRUFBRSwrQkFBZ0I7SUFDMUMsQ0FBQyxpQkFBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLHFDQUFtQjtJQUNoRCxDQUFDLGlCQUFTLENBQUMsV0FBVyxDQUFDLEVBQUUsNkJBQWU7Q0FDM0MsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsU0FBZ0IsZUFBZSxDQUFDLE1BQXVCO0lBQ25ELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBc0IsQ0FBQztJQUMzRCw0RUFBNEU7SUFDNUUsd0VBQXdFO0lBQ3hFLDBFQUEwRTtJQUMxRSwyRUFBMkU7SUFDM0UseUVBQXlFO0lBQ3pFLDZCQUE2QjtJQUM3QixNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksK0JBQWdCLENBQUM7SUFDNUQsT0FBTyxJQUFJLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNuQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSZWdpc3RyeSBtYXBwaW5nIHRoZSBgdGFibGVUeXBlYCBzdHJpbmcgdG8gdGhlIGNvbmNyZXRlIGBUYWJsZVR5cGVCYXNlYFxuICogc3ViY2xhc3MgdGhhdCBpbXBsZW1lbnRzIGl0LiBBZGRpbmcgYSBuZXcgZW5naW5lIGlzIGEgbWF0dGVyIG9mIHdyaXRpbmcgYVxuICogc3ViY2xhc3MgYW5kIGFkZGluZyBvbmUgZW50cnkgaGVyZS5cbiAqL1xuXG5pbXBvcnQge1xuICAgIFRhYmxlVHlwZSxcbn0gZnJvbSAnLi4vbW9kZWwnO1xuaW1wb3J0IHtcbiAgICBUYWJsZVR5cGVCYXNlLFxuICAgIFRhYmxlVHlwZUZpZWxkcyxcbn0gZnJvbSAnLi4vdGFibGUtdHlwZSc7XG5pbXBvcnQge1xuICAgIEhpdmVQYXJxdWV0VGFibGUsXG59IGZyb20gJy4vaGl2ZS1wYXJxdWV0JztcbmltcG9ydCB7XG4gICAgSWNlYmVyZ1BhcnF1ZXRUYWJsZSxcbn0gZnJvbSAnLi9pY2ViZXJnLXBhcnF1ZXQnO1xuaW1wb3J0IHtcbiAgICBQb3N0Z3JlczE4VGFibGUsXG59IGZyb20gJy4vcG9zdGdyZXMtMTgnO1xuXG4vKiogQ29uc3RydWN0b3Igc2lnbmF0dXJlIHNoYXJlZCBieSBldmVyeSBjb25jcmV0ZSB0YWJsZSBzdWJjbGFzcy4gKi9cbnR5cGUgVGFibGVUeXBlQ29uc3RydWN0b3IgPSBuZXcgKGZpZWxkczogVGFibGVUeXBlRmllbGRzKSA9PiBUYWJsZVR5cGVCYXNlO1xuXG4vLy8gRXhoYXVzdGl2ZSBtYXA6IGV2ZXJ5IHZhbHVlIG9mIHRoZSBgVGFibGVUeXBlYCBlbnVtIGhhcyBhIGNvbmNyZXRlIHN1YmNsYXNzLlxuY29uc3QgUkVHSVNUUlk6IFJlY29yZDxUYWJsZVR5cGUsIFRhYmxlVHlwZUNvbnN0cnVjdG9yPiA9IHtcbiAgICBbVGFibGVUeXBlLkhJVkVfUEFSUVVFVF06IEhpdmVQYXJxdWV0VGFibGUsXG4gICAgW1RhYmxlVHlwZS5JQ0VCRVJHX1BBUlFVRVRdOiBJY2ViZXJnUGFycXVldFRhYmxlLFxuICAgIFtUYWJsZVR5cGUuUE9TVEdSRVNfMThdOiBQb3N0Z3JlczE4VGFibGUsXG59O1xuXG4vKipcbiAqIEJ1aWxkIHRoZSBjb25jcmV0ZSBgVGFibGVUeXBlQmFzZWAgc3ViY2xhc3MgZm9yIHRoZSBnaXZlbiBmaWVsZHMuXG4gKlxuICogQHBhcmFtIGZpZWxkcyBUaGUgbm9ybWFsaXplZCB0YWJsZSBmaWVsZHMuXG4gKiBAcmV0dXJucyBBIGNvbmNyZXRlIHRhYmxlIGluc3RhbmNlIGZvciB0aGUgZW5naW5lIG5hbWVkIGJ5IGBmaWVsZHMuZGVmaW5pdGlvbi50YWJsZVR5cGVgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVGFibGVUeXBlKGZpZWxkczogVGFibGVUeXBlRmllbGRzKTogVGFibGVUeXBlQmFzZSB7XG4gICAgY29uc3QgdGFibGVUeXBlID0gZmllbGRzLmRlZmluaXRpb24udGFibGVUeXBlIGFzIFRhYmxlVHlwZTtcbiAgICAvLy8gQW4gdW5yZWNvZ25pemVkIGB0YWJsZVR5cGVgIG9ubHkgb2NjdXJzIHdoZW4gTGF5ZXIgMSBhbHJlYWR5IGZsYWdnZWQgdGhlXG4gICAgLy8vIGZpbGU6IHN1Y2ggdGFibGVzIGFyZSBza2lwcGVkIGJ5IGludHJhLXRhYmxlIHJ1bGVzIGFuZCBza2lwcGVkIGFzIEZLXG4gICAgLy8vIHRhcmdldHMsIHNvIHRoZSBjaG9pY2UgaGVyZSBpcyBwdXJlbHkgZm9yIGNyb3NzLWZpbGUgKnJlc29sdXRpb24qICh0aGVcbiAgICAvLy8gaW5zdGFuY2Ugc3RpbGwgbmVlZHMgdG8gbGFuZCBpbiBgd29ybGQudGFibGVzYCBzbyBkZXBlbmRzT24gLyBGSyBzb3VyY2VcbiAgICAvLy8gbG9va3VwcyBkb24ndCBwcmV0ZW5kIHRoZSBmaWxlIGlzIG1pc3NpbmcpLiBgSGl2ZVBhcnF1ZXRUYWJsZWAgaXMgdGhlXG4gICAgLy8vIHJlc29sdXRpb24tb25seSBmYWxsYmFjay5cbiAgICBjb25zdCBDb25zdHJ1Y3RvciA9IFJFR0lTVFJZW3RhYmxlVHlwZV0gPz8gSGl2ZVBhcnF1ZXRUYWJsZTtcbiAgICByZXR1cm4gbmV3IENvbnN0cnVjdG9yKGZpZWxkcyk7XG59XG4iXX0=
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-engine column-type registries for Hive and Postgres.
|
|
3
|
+
*
|
|
4
|
+
* Each function answers "is this type string valid for this engine?". The
|
|
5
|
+
* concrete `TableTypeBase` subclasses delegate `isValidColumnType` here (and
|
|
6
|
+
* the Iceberg subclass delegates to `./iceberg`).
|
|
7
|
+
*/
|
|
8
|
+
/** Whether the string is a valid Hive (parquet) column type. */
|
|
9
|
+
export declare function isValidHiveType(typeStr: string): boolean;
|
|
10
|
+
/** Whether the string is a valid Postgres 18 column type. */
|
|
11
|
+
export declare function isValidPostgresType(typeStr: string): boolean;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Per-engine column-type registries for Hive and Postgres.
|
|
4
|
+
*
|
|
5
|
+
* Each function answers "is this type string valid for this engine?". The
|
|
6
|
+
* concrete `TableTypeBase` subclasses delegate `isValidColumnType` here (and
|
|
7
|
+
* the Iceberg subclass delegates to `./iceberg`).
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.isValidHiveType = isValidHiveType;
|
|
11
|
+
exports.isValidPostgresType = isValidPostgresType;
|
|
12
|
+
/// ////////////////////////////////////////////////////////////////////////////
|
|
13
|
+
// Hive
|
|
14
|
+
const HIVE_PRIMITIVES = new Set([
|
|
15
|
+
'tinyint',
|
|
16
|
+
'smallint',
|
|
17
|
+
'int',
|
|
18
|
+
'integer',
|
|
19
|
+
'bigint',
|
|
20
|
+
'boolean',
|
|
21
|
+
'float',
|
|
22
|
+
'double',
|
|
23
|
+
'double precision',
|
|
24
|
+
'string',
|
|
25
|
+
'binary',
|
|
26
|
+
'timestamp',
|
|
27
|
+
'date',
|
|
28
|
+
'interval',
|
|
29
|
+
]);
|
|
30
|
+
/**
|
|
31
|
+
* Split a generic-type body on top-level commas (ignoring commas nested inside
|
|
32
|
+
* `<...>`).
|
|
33
|
+
*
|
|
34
|
+
* @param body Inner text of a generic type.
|
|
35
|
+
* @returns The top-level comma-separated parts.
|
|
36
|
+
*/
|
|
37
|
+
function splitTopLevel(body) {
|
|
38
|
+
const parts = [];
|
|
39
|
+
let depth = 0;
|
|
40
|
+
let current = '';
|
|
41
|
+
for (const char of body) {
|
|
42
|
+
if (char === '<') {
|
|
43
|
+
depth += 1;
|
|
44
|
+
}
|
|
45
|
+
else if (char === '>') {
|
|
46
|
+
depth -= 1;
|
|
47
|
+
}
|
|
48
|
+
if (char === ',' && depth === 0) {
|
|
49
|
+
parts.push(current);
|
|
50
|
+
current = '';
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
current += char;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
parts.push(current);
|
|
57
|
+
return parts.map((part) => part.trim());
|
|
58
|
+
}
|
|
59
|
+
function isValidHiveStructField(field) {
|
|
60
|
+
const colon = field.indexOf(':');
|
|
61
|
+
if (colon <= 0) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const name = field.slice(0, colon).trim();
|
|
65
|
+
const type = field.slice(colon + 1).trim();
|
|
66
|
+
return name.length > 0 && isValidHiveType(type);
|
|
67
|
+
}
|
|
68
|
+
/** Whether the string is a valid Hive (parquet) column type. */
|
|
69
|
+
function isValidHiveType(typeStr) {
|
|
70
|
+
const type = typeStr.trim().toLowerCase();
|
|
71
|
+
if (HIVE_PRIMITIVES.has(type)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
if (/^decimal\(\d+(,\s*\d+)?\)$/.test(type)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if (/^(varchar|char)\(\d+\)$/.test(type)) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
const open = type.indexOf('<');
|
|
81
|
+
if (open > 0 && type.endsWith('>')) {
|
|
82
|
+
const ctor = type.slice(0, open);
|
|
83
|
+
const inner = type.slice(open + 1, -1);
|
|
84
|
+
const parts = splitTopLevel(inner);
|
|
85
|
+
switch (ctor) {
|
|
86
|
+
case 'array':
|
|
87
|
+
return parts.length === 1 && isValidHiveType(parts[0]);
|
|
88
|
+
case 'map':
|
|
89
|
+
return parts.length === 2 && parts.every(isValidHiveType);
|
|
90
|
+
case 'uniontype':
|
|
91
|
+
return parts.length >= 1 && parts.every(isValidHiveType);
|
|
92
|
+
case 'struct':
|
|
93
|
+
return parts.length >= 1 && parts.every(isValidHiveStructField);
|
|
94
|
+
default:
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
/// ////////////////////////////////////////////////////////////////////////////
|
|
101
|
+
// Postgres
|
|
102
|
+
const POSTGRES_EXACT = new Set([
|
|
103
|
+
'smallint',
|
|
104
|
+
'integer',
|
|
105
|
+
'int',
|
|
106
|
+
'int2',
|
|
107
|
+
'int4',
|
|
108
|
+
'int8',
|
|
109
|
+
'bigint',
|
|
110
|
+
'real',
|
|
111
|
+
'float4',
|
|
112
|
+
'float8',
|
|
113
|
+
'double precision',
|
|
114
|
+
'money',
|
|
115
|
+
'text',
|
|
116
|
+
'bytea',
|
|
117
|
+
'boolean',
|
|
118
|
+
'bool',
|
|
119
|
+
'date',
|
|
120
|
+
'timestamp',
|
|
121
|
+
'timestamptz',
|
|
122
|
+
'timestamp with time zone',
|
|
123
|
+
'time',
|
|
124
|
+
'timetz',
|
|
125
|
+
'time with time zone',
|
|
126
|
+
'interval',
|
|
127
|
+
'uuid',
|
|
128
|
+
'json',
|
|
129
|
+
'jsonb',
|
|
130
|
+
'xml',
|
|
131
|
+
'inet',
|
|
132
|
+
'cidr',
|
|
133
|
+
'macaddr',
|
|
134
|
+
'macaddr8',
|
|
135
|
+
'smallserial',
|
|
136
|
+
'serial',
|
|
137
|
+
'bigserial',
|
|
138
|
+
'serial2',
|
|
139
|
+
'serial4',
|
|
140
|
+
'serial8',
|
|
141
|
+
'varchar',
|
|
142
|
+
'char',
|
|
143
|
+
'character',
|
|
144
|
+
'character varying',
|
|
145
|
+
'bpchar',
|
|
146
|
+
'numeric',
|
|
147
|
+
'decimal',
|
|
148
|
+
'bit',
|
|
149
|
+
'varbit',
|
|
150
|
+
'bit varying',
|
|
151
|
+
]);
|
|
152
|
+
const POSTGRES_PARAM_ALLOWED = new Set([
|
|
153
|
+
'varchar',
|
|
154
|
+
'char',
|
|
155
|
+
'character',
|
|
156
|
+
'character varying',
|
|
157
|
+
'bpchar',
|
|
158
|
+
'numeric',
|
|
159
|
+
'decimal',
|
|
160
|
+
'bit',
|
|
161
|
+
'varbit',
|
|
162
|
+
'bit varying',
|
|
163
|
+
'time',
|
|
164
|
+
'timetz',
|
|
165
|
+
'timestamp',
|
|
166
|
+
'timestamptz',
|
|
167
|
+
'interval',
|
|
168
|
+
]);
|
|
169
|
+
/** Whether the string is a valid Postgres 18 column type. */
|
|
170
|
+
function isValidPostgresType(typeStr) {
|
|
171
|
+
let type = typeStr.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
172
|
+
/// Strip one or more trailing array markers (`[]`, `[3]`).
|
|
173
|
+
type = type.replace(/(\s*\[\s*\d*\s*\])+$/, '').trim();
|
|
174
|
+
const paramMatch = /^(.*?)\(([^)]*)\)$/.exec(type);
|
|
175
|
+
if (paramMatch) {
|
|
176
|
+
const base = paramMatch[1].trim();
|
|
177
|
+
const params = paramMatch[2].trim();
|
|
178
|
+
return POSTGRES_PARAM_ALLOWED.has(base) && /^\d+(\s*,\s*\d+)?$/.test(params);
|
|
179
|
+
}
|
|
180
|
+
return POSTGRES_EXACT.has(type);
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7QUE2REgsMENBbUNDO0FBMkVELGtEQWNDO0FBdkxELGdGQUFnRjtBQUNoRixPQUFPO0FBRVAsTUFBTSxlQUFlLEdBQXdCLElBQUksR0FBRyxDQUFDO0lBQ2pELFNBQVM7SUFDVCxVQUFVO0lBQ1YsS0FBSztJQUNMLFNBQVM7SUFDVCxRQUFRO0lBQ1IsU0FBUztJQUNULE9BQU87SUFDUCxRQUFRO0lBQ1Isa0JBQWtCO0lBQ2xCLFFBQVE7SUFDUixRQUFRO0lBQ1IsV0FBVztJQUNYLE1BQU07SUFDTixVQUFVO0NBQ2IsQ0FBQyxDQUFDO0FBRUg7Ozs7OztHQU1HO0FBQ0gsU0FBUyxhQUFhLENBQUMsSUFBWTtJQUMvQixNQUFNLEtBQUssR0FBYSxFQUFFLENBQUM7SUFDM0IsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ2QsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO0lBQ2pCLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdEIsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDZixLQUFLLElBQUksQ0FBQyxDQUFDO1FBQ2YsQ0FBQzthQUFNLElBQUksSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO1lBQ3RCLEtBQUssSUFBSSxDQUFDLENBQUM7UUFDZixDQUFDO1FBQ0QsSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLEtBQUssS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM5QixLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3BCLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDakIsQ0FBQzthQUFNLENBQUM7WUFDSixPQUFPLElBQUksSUFBSSxDQUFDO1FBQ3BCLENBQUM7SUFDTCxDQUFDO0lBQ0QsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENB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QUM7SUFDbkQsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNiLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsQyxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDcEMsT0FBTyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksb0JBQW9CLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2pGLENBQUM7SUFFRCxPQUFPLGNBQWMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDcEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUGVyLWVuZ2luZSBjb2x1bW4tdHlwZSByZWdpc3RyaWVzIGZvciBIaXZlIGFuZCBQb3N0Z3Jlcy5cbiAqXG4gKiBFYWNoIGZ1bmN0aW9uIGFuc3dlcnMgXCJpcyB0aGlzIHR5cGUgc3RyaW5nIHZhbGlkIGZvciB0aGlzIGVuZ2luZT9cIi4gVGhlXG4gKiBjb25jcmV0ZSBgVGFibGVUeXBlQmFzZWAgc3ViY2xhc3NlcyBkZWxlZ2F0ZSBgaXNWYWxpZENvbHVtblR5cGVgIGhlcmUgKGFuZFxuICogdGhlIEljZWJlcmcgc3ViY2xhc3MgZGVsZWdhdGVzIHRvIGAuL2ljZWJlcmdgKS5cbiAqL1xuXG4vLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gSGl2ZVxuXG5jb25zdCBISVZFX1BSSU1JVElWRVM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFtcbiAgICAndGlueWludCcsXG4gICAgJ3NtYWxsaW50JyxcbiAgICAnaW50JyxcbiAgICAnaW50ZWdlcicsXG4gICAgJ2JpZ2ludCcsXG4gICAgJ2Jvb2xlYW4nLFxuICAgICdmbG9hdCcsXG4gICAgJ2RvdWJsZScsXG4gICAgJ2RvdWJsZSBwcmVjaXNpb24nLFxuICAgICdzdHJpbmcnLFxuICAgICdiaW5hcnknLFxuICAgICd0aW1lc3RhbXAnLFxuICAgICdkYXRlJyxcbiAgICAnaW50ZXJ2YWwnLFxuXSk7XG5cbi8qKlxuICogU3BsaXQgYSBnZW5lcmljLXR5cGUgYm9keSBvbiB0b3AtbGV2ZWwgY29tbWFzIChpZ25vcmluZyBjb21tYXMgbmVzdGVkIGluc2lkZVxuICogYDwuLi4+YCkuXG4gKlxuICogQHBhcmFtIGJvZHkgSW5uZXIgdGV4dCBvZiBhIGdlbmVyaWMgdHlwZS5cbiAqIEByZXR1cm5zIFRoZSB0b3AtbGV2ZWwgY29tbWEtc2VwYXJhdGVkIHBhcnRzLlxuICovXG5mdW5jdGlvbiBzcGxpdFRvcExldmVsKGJvZHk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBwYXJ0czogc3RyaW5nW10gPSBbXTtcbiAgICBsZXQgZGVwdGggPSAwO1xuICAgIGxldCBjdXJyZW50ID0gJyc7XG4gICAgZm9yIChjb25zdCBjaGFyIG9mIGJvZHkpIHtcbiAgICAgICAgaWYgKGNoYXIgPT09ICc8Jykge1xuICAgICAgICAgICAgZGVwdGggKz0gMTtcbiAgICAgICAgfSBlbHNlIGlmIChjaGFyID09PSAnPicpIHtcbiAgICAgICAgICAgIGRlcHRoIC09IDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYXIgPT09ICcsJyAmJiBkZXB0aCA9PT0gMCkge1xuICAgICAgICAgICAgcGFydHMucHVzaChjdXJyZW50KTtcbiAgICAgICAgICAgIGN1cnJlbnQgPSAnJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN1cnJlbnQgKz0gY2hhcjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBwYXJ0cy5wdXNoKGN1cnJlbnQpO1xuICAgIHJldHVybiBwYXJ0cy5tYXAoKHBhcnQpID0+IHBhcnQudHJpbSgpKTtcbn1cblxuZnVuY3Rpb24gaXNWYWxpZEhpdmVTdHJ1Y3RGaWVsZChmaWVsZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY29sb24gPSBmaWVsZC5pbmRleE9mKCc6Jyk7XG4gICAgaWYgKGNvbG9uIDw9IDApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBuYW1lID0gZmllbGQuc2xpY2UoMCwgY29sb24pLnRyaW0oKTtcbiAgICBjb25zdCB0eXBlID0gZmllbGQuc2xpY2UoY29sb24gKyAxKS50cmltKCk7XG4gICAgcmV0dXJuIG5hbWUubGVuZ3RoID4gMCAmJiBpc1ZhbGlkSGl2ZVR5cGUodHlwZSk7XG59XG5cbi8qKiBXaGV0aGVyIHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBIaXZlIChwYXJxdWV0KSBjb2x1bW4gdHlwZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkSGl2ZVR5cGUodHlwZVN0cjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgdHlwZSA9IHR5cGVTdHIudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICBpZiAoSElWRV9QUklNSVRJVkVTLmhhcyh0eXBlKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoL15kZWNpbWFsXFwoXFxkKygsXFxzKlxcZCspP1xcKSQvLnRlc3QodHlwZSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKC9eKHZhcmNoYXJ8Y2hhcilcXChcXGQrXFwpJC8udGVzdCh0eXBlKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zdCBvcGVuID0gdHlwZS5pbmRleE9mKCc8Jyk7XG4gICAgaWYgKG9wZW4gPiAwICYmIHR5cGUuZW5kc1dpdGgoJz4nKSkge1xuICAgICAgICBjb25zdCBjdG9yID0gdHlwZS5zbGljZSgwLCBvcGVuKTtcbiAgICAgICAgY29uc3QgaW5uZXIgPSB0eXBlLnNsaWNlKG9wZW4gKyAxLCAtMSk7XG4gICAgICAgIGNvbnN0IHBhcnRzID0gc3BsaXRUb3BMZXZlbChpbm5lcik7XG4gICAgICAgIHN3aXRjaCAoY3Rvcikge1xuICAgICAgICAgICAgY2FzZSAnYXJyYXknOlxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJ0cy5sZW5ndGggPT09IDEgJiYgaXNWYWxpZEhpdmVUeXBlKHBhcnRzWzBdKTtcbiAgICAgICAgICAgIGNhc2UgJ21hcCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnRzLmxlbmd0aCA9PT0gMiAmJiBwYXJ0cy5ldmVyeShpc1ZhbGlkSGl2ZVR5cGUpO1xuICAgICAgICAgICAgY2FzZSAndW5pb250eXBlJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFydHMubGVuZ3RoID49IDEgJiYgcGFydHMuZXZlcnkoaXNWYWxpZEhpdmVUeXBlKTtcbiAgICAgICAgICAgIGNhc2UgJ3N0cnVjdCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnRzLmxlbmd0aCA+PSAxICYmIHBhcnRzLmV2ZXJ5KGlzVmFsaWRIaXZlU3RydWN0RmllbGQpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8vLyAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBQb3N0Z3Jlc1xuXG5jb25zdCBQT1NUR1JFU19FWEFDVDogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoW1xuICAgICdzbWFsbGludCcsXG4gICAgJ2ludGVnZXInLFxuICAgICdpbnQnLFxuICAgICdpbnQyJyxcbiAgICAnaW50NCcsXG4gICAgJ2ludDgnLFxuICAgICdiaWdpbnQnLFxuICAgICdyZWFsJyxcbiAgICAnZmxvYXQ0JyxcbiAgICAnZmxvYXQ4JyxcbiAgICAnZG91YmxlIHByZWNpc2lvbicsXG4gICAgJ21vbmV5JyxcbiAgICAndGV4dCcsXG4gICAgJ2J5dGVhJyxcbiAgICAnYm9vbGVhbicsXG4gICAgJ2Jvb2wnLFxuICAgICdkYXRlJyxcbiAgICAndGltZXN0YW1wJyxcbiAgICAndGltZXN0YW1wdHonLFxuICAgICd0aW1lc3RhbXAgd2l0aCB0aW1lIHpvbmUnLFxuICAgICd0aW1lJyxcbiAgICAndGltZXR6JyxcbiAgICAndGltZSB3aXRoIHRpbWUgem9uZScsXG4gICAgJ2ludGVydmFsJyxcbiAgICAndXVpZCcsXG4gICAgJ2pzb24nLFxuICAgICdqc29uYicsXG4gICAgJ3htbCcsXG4gICAgJ2luZXQnLFxuICAgICdjaWRyJyxcbiAgICAnbWFjYWRkcicsXG4gICAgJ21hY2FkZHI4JyxcbiAgICAnc21hbGxzZXJpYWwnLFxuICAgICdzZXJpYWwnLFxuICAgICdiaWdzZXJpYWwnLFxuICAgICdzZXJpYWwyJyxcbiAgICAnc2VyaWFsNCcsXG4gICAgJ3NlcmlhbDgnLFxuICAgICd2YXJjaGFyJyxcbiAgICAnY2hhcicsXG4gICAgJ2NoYXJhY3RlcicsXG4gICAgJ2NoYXJhY3RlciB2YXJ5aW5nJyxcbiAgICAnYnBjaGFyJyxcbiAgICAnbnVtZXJpYycsXG4gICAgJ2RlY2ltYWwnLFxuICAgICdiaXQnLFxuICAgICd2YXJiaXQnLFxuICAgICdiaXQgdmFyeWluZycsXG5dKTtcblxuY29uc3QgUE9TVEdSRVNfUEFSQU1fQUxMT1dFRDogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoW1xuICAgICd2YXJjaGFyJyxcbiAgICAnY2hhcicsXG4gICAgJ2NoYXJhY3RlcicsXG4gICAgJ2NoYXJhY3RlciB2YXJ5aW5nJyxcbiAgICAnYnBjaGFyJyxcbiAgICAnbnVtZXJpYycsXG4gICAgJ2RlY2ltYWwnLFxuICAgICdiaXQnLFxuICAgICd2YXJiaXQnLFxuICAgICdiaXQgdmFyeWluZycsXG4gICAgJ3RpbWUnLFxuICAgICd0aW1ldHonLFxuICAgICd0aW1lc3RhbXAnLFxuICAgICd0aW1lc3RhbXB0eicsXG4gICAgJ2ludGVydmFsJyxcbl0pO1xuXG4vKiogV2hldGhlciB0aGUgc3RyaW5nIGlzIGEgdmFsaWQgUG9zdGdyZXMgMTggY29sdW1uIHR5cGUuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFBvc3RncmVzVHlwZSh0eXBlU3RyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBsZXQgdHlwZSA9IHR5cGVTdHIudHJpbSgpLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFxzKy9nLCAnICcpO1xuXG4gICAgLy8vIFN0cmlwIG9uZSBvciBtb3JlIHRyYWlsaW5nIGFycmF5IG1hcmtlcnMgKGBbXWAsIGBbM11gKS5cbiAgICB0eXBlID0gdHlwZS5yZXBsYWNlKC8oXFxzKlxcW1xccypcXGQqXFxzKlxcXSkrJC8sICcnKS50cmltKCk7XG5cbiAgICBjb25zdCBwYXJhbU1hdGNoID0gL14oLio/KVxcKChbXildKilcXCkkLy5leGVjKHR5cGUpO1xuICAgIGlmIChwYXJhbU1hdGNoKSB7XG4gICAgICAgIGNvbnN0IGJhc2UgPSBwYXJhbU1hdGNoWzFdLnRyaW0oKTtcbiAgICAgICAgY29uc3QgcGFyYW1zID0gcGFyYW1NYXRjaFsyXS50cmltKCk7XG4gICAgICAgIHJldHVybiBQT1NUR1JFU19QQVJBTV9BTExPV0VELmhhcyhiYXNlKSAmJiAvXlxcZCsoXFxzKixcXHMqXFxkKyk/JC8udGVzdChwYXJhbXMpO1xuICAgIH1cblxuICAgIHJldHVybiBQT1NUR1JFU19FWEFDVC5oYXModHlwZSk7XG59XG4iXX0=
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level validation: load a dataset root (Layer 1) and run the semantic
|
|
3
|
+
* rules (Layer 2), aggregating every violation.
|
|
4
|
+
*/
|
|
5
|
+
import { ValidationResult } from './model';
|
|
6
|
+
/**
|
|
7
|
+
* Validate a dataset root.
|
|
8
|
+
*
|
|
9
|
+
* @param rootDir Path to the dataset root.
|
|
10
|
+
* @returns The aggregate result. `ok` is false when any error-level violation exists.
|
|
11
|
+
* @throws Error When `rootDir` is not an existing directory.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateRoot(rootDir: string): ValidationResult;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Top-level validation: load a dataset root (Layer 1) and run the semantic
|
|
4
|
+
* rules (Layer 2), aggregating every violation.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.validateRoot = validateRoot;
|
|
8
|
+
const loader_1 = require("./loader");
|
|
9
|
+
const world_1 = require("./world");
|
|
10
|
+
/**
|
|
11
|
+
* Validate a dataset root.
|
|
12
|
+
*
|
|
13
|
+
* @param rootDir Path to the dataset root.
|
|
14
|
+
* @returns The aggregate result. `ok` is false when any error-level violation exists.
|
|
15
|
+
* @throws Error When `rootDir` is not an existing directory.
|
|
16
|
+
*/
|
|
17
|
+
function validateRoot(rootDir) {
|
|
18
|
+
const { world, violations, } = (0, loader_1.loadRoot)(rootDir);
|
|
19
|
+
const semantic = (0, world_1.runSemanticRules)(world);
|
|
20
|
+
const all = [
|
|
21
|
+
...violations,
|
|
22
|
+
...semantic,
|
|
23
|
+
];
|
|
24
|
+
const ok = !all.some((violation) => violation.level === 'error');
|
|
25
|
+
return {
|
|
26
|
+
ok,
|
|
27
|
+
violations: all,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdmFsaWRhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7QUFtQkgsb0NBY0M7QUE1QkQscUNBRWtCO0FBQ2xCLG1DQUVpQjtBQUVqQjs7Ozs7O0dBTUc7QUFDSCxTQUFnQixZQUFZLENBQUMsT0FBZTtJQUN4QyxNQUFNLEVBQ0YsS0FBSyxFQUFFLFVBQVUsR0FDcEIsR0FBRyxJQUFBLGlCQUFRLEVBQUMsT0FBTyxDQUFDLENBQUM7SUFDdEIsTUFBTSxRQUFRLEdBQUcsSUFBQSx3QkFBZ0IsRUFBQyxLQUFLLENBQUMsQ0FBQztJQUN6QyxNQUFNLEdBQUcsR0FBRztRQUNSLEdBQUcsVUFBVTtRQUNiLEdBQUcsUUFBUTtLQUNkLENBQUM7SUFDRixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDLENBQUM7SUFDakUsT0FBTztRQUNILEVBQUU7UUFDRixVQUFVLEVBQUUsR0FBRztLQUNsQixDQUFDO0FBQ04sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVG9wLWxldmVsIHZhbGlkYXRpb246IGxvYWQgYSBkYXRhc2V0IHJvb3QgKExheWVyIDEpIGFuZCBydW4gdGhlIHNlbWFudGljXG4gKiBydWxlcyAoTGF5ZXIgMiksIGFnZ3JlZ2F0aW5nIGV2ZXJ5IHZpb2xhdGlvbi5cbiAqL1xuXG5pbXBvcnQge1xuICAgIFZhbGlkYXRpb25SZXN1bHQsXG59IGZyb20gJy4vbW9kZWwnO1xuaW1wb3J0IHtcbiAgICBsb2FkUm9vdCxcbn0gZnJvbSAnLi9sb2FkZXInO1xuaW1wb3J0IHtcbiAgICBydW5TZW1hbnRpY1J1bGVzLFxufSBmcm9tICcuL3dvcmxkJztcblxuLyoqXG4gKiBWYWxpZGF0ZSBhIGRhdGFzZXQgcm9vdC5cbiAqXG4gKiBAcGFyYW0gcm9vdERpciBQYXRoIHRvIHRoZSBkYXRhc2V0IHJvb3QuXG4gKiBAcmV0dXJucyBUaGUgYWdncmVnYXRlIHJlc3VsdC4gYG9rYCBpcyBmYWxzZSB3aGVuIGFueSBlcnJvci1sZXZlbCB2aW9sYXRpb24gZXhpc3RzLlxuICogQHRocm93cyBFcnJvciBXaGVuIGByb290RGlyYCBpcyBub3QgYW4gZXhpc3RpbmcgZGlyZWN0b3J5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVSb290KHJvb3REaXI6IHN0cmluZyk6IFZhbGlkYXRpb25SZXN1bHQge1xuICAgIGNvbnN0IHtcbiAgICAgICAgd29ybGQsIHZpb2xhdGlvbnMsIFxuICAgIH0gPSBsb2FkUm9vdChyb290RGlyKTtcbiAgICBjb25zdCBzZW1hbnRpYyA9IHJ1blNlbWFudGljUnVsZXMod29ybGQpO1xuICAgIGNvbnN0IGFsbCA9IFtcbiAgICAgICAgLi4udmlvbGF0aW9ucyxcbiAgICAgICAgLi4uc2VtYW50aWMsXG4gICAgXTtcbiAgICBjb25zdCBvayA9ICFhbGwuc29tZSgodmlvbGF0aW9uKSA9PiB2aW9sYXRpb24ubGV2ZWwgPT09ICdlcnJvcicpO1xuICAgIHJldHVybiB7XG4gICAgICAgIG9rLFxuICAgICAgICB2aW9sYXRpb25zOiBhbGwsXG4gICAgfTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The world: the in-memory representation of a loaded dataset root, plus the
|
|
3
|
+
* top-level semantic-rule runner.
|
|
4
|
+
*
|
|
5
|
+
* A `World` holds every schema and every table (as a concrete
|
|
6
|
+
* `TableTypeBase` instance). `runSemanticRules` walks the world, asking each
|
|
7
|
+
* structurally-valid table for its intra-table and cross-file violations,
|
|
8
|
+
* then appends the one global rule that has to see the whole graph at once
|
|
9
|
+
* (cycle detection).
|
|
10
|
+
*/
|
|
11
|
+
import { SchemaDescription, Violation } from './model';
|
|
12
|
+
import type { TableTypeBase } from './table-type';
|
|
13
|
+
/** A schema loaded from disk. */
|
|
14
|
+
export interface LoadedSchema {
|
|
15
|
+
/** Schema name (the folder name). */
|
|
16
|
+
readonly name: string;
|
|
17
|
+
/** Absolute path to the schema folder. */
|
|
18
|
+
readonly dirPath: string;
|
|
19
|
+
/** Description from `<schema>.json`, or null if that file is missing. */
|
|
20
|
+
readonly description: SchemaDescription | null;
|
|
21
|
+
/** Tables in this schema. */
|
|
22
|
+
readonly tables: TableTypeBase[];
|
|
23
|
+
}
|
|
24
|
+
/** The whole loaded dataset root. */
|
|
25
|
+
export interface World {
|
|
26
|
+
/** Absolute path to the root. */
|
|
27
|
+
readonly rootDir: string;
|
|
28
|
+
/** Schemas keyed by name. */
|
|
29
|
+
readonly schemas: Map<string, LoadedSchema>;
|
|
30
|
+
/** Tables keyed by `schema.table`. */
|
|
31
|
+
readonly tables: Map<string, TableTypeBase>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Run all semantic rules over a world.
|
|
35
|
+
*
|
|
36
|
+
* @param world The loaded dataset root.
|
|
37
|
+
* @returns Every semantic violation found.
|
|
38
|
+
*/
|
|
39
|
+
export declare function runSemanticRules(world: World): Violation[];
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The world: the in-memory representation of a loaded dataset root, plus the
|
|
4
|
+
* top-level semantic-rule runner.
|
|
5
|
+
*
|
|
6
|
+
* A `World` holds every schema and every table (as a concrete
|
|
7
|
+
* `TableTypeBase` instance). `runSemanticRules` walks the world, asking each
|
|
8
|
+
* structurally-valid table for its intra-table and cross-file violations,
|
|
9
|
+
* then appends the one global rule that has to see the whole graph at once
|
|
10
|
+
* (cycle detection).
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.runSemanticRules = runSemanticRules;
|
|
14
|
+
/// DEPENDENCY_GRAPH_ACYCLIC — the dependsOn graph has no cycles.
|
|
15
|
+
///
|
|
16
|
+
/// Standard three-colour DFS. Each back-edge (a dependency pointing at a table
|
|
17
|
+
/// still on the current stack) closes a cycle and is detected exactly once,
|
|
18
|
+
/// because every table is coloured grey then black a single time. This rule
|
|
19
|
+
/// stays a free function because it operates on the whole graph at once, not
|
|
20
|
+
/// on any single table in isolation.
|
|
21
|
+
function acyclicViolations(world) {
|
|
22
|
+
const violations = [];
|
|
23
|
+
const white = new Set(world.tables.keys());
|
|
24
|
+
const gray = new Set();
|
|
25
|
+
const visit = (table, stack) => {
|
|
26
|
+
const node = table.qualifiedName;
|
|
27
|
+
white.delete(node);
|
|
28
|
+
gray.add(node);
|
|
29
|
+
stack.push(node);
|
|
30
|
+
for (const dependency of table.definition.dependsOn) {
|
|
31
|
+
const dependencyTable = world.tables.get(dependency);
|
|
32
|
+
if (dependencyTable === undefined) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (gray.has(dependency)) {
|
|
36
|
+
const cycle = [
|
|
37
|
+
...stack.slice(stack.indexOf(dependency)),
|
|
38
|
+
dependency,
|
|
39
|
+
];
|
|
40
|
+
violations.push({
|
|
41
|
+
level: 'error',
|
|
42
|
+
code: 'DEPENDENCY_GRAPH_ACYCLIC',
|
|
43
|
+
schema: table.schema,
|
|
44
|
+
table: table.name,
|
|
45
|
+
path: table.filePath,
|
|
46
|
+
field: 'dependsOn',
|
|
47
|
+
message: `dependency cycle detected: ${cycle.join(' -> ')}`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else if (white.has(dependency)) {
|
|
51
|
+
visit(dependencyTable, stack);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
stack.pop();
|
|
55
|
+
gray.delete(node);
|
|
56
|
+
};
|
|
57
|
+
for (const table of world.tables.values()) {
|
|
58
|
+
if (white.has(table.qualifiedName)) {
|
|
59
|
+
visit(table, []);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return violations;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Run all semantic rules over a world.
|
|
66
|
+
*
|
|
67
|
+
* @param world The loaded dataset root.
|
|
68
|
+
* @returns Every semantic violation found.
|
|
69
|
+
*/
|
|
70
|
+
function runSemanticRules(world) {
|
|
71
|
+
const violations = [];
|
|
72
|
+
for (const table of world.tables.values()) {
|
|
73
|
+
if (!table.structurallyValid) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
violations.push(...table.intraTableViolations());
|
|
77
|
+
violations.push(...table.crossFileViolations(world));
|
|
78
|
+
}
|
|
79
|
+
violations.push(...acyclicViolations(world));
|
|
80
|
+
return violations;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ybGQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd29ybGQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7R0FTRzs7QUFrR0gsNENBV0M7QUF4RUQsaUVBQWlFO0FBQ2pFLEdBQUc7QUFDSCwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDRFQUE0RTtBQUM1RSw2RUFBNkU7QUFDN0UscUNBQXFDO0FBQ3JDLFNBQVMsaUJBQWlCLENBQUMsS0FBWTtJQUNuQyxNQUFNLFVBQVUsR0FBZ0IsRUFBRSxDQUFDO0lBQ25DLE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMzQyxNQUFNLElBQUksR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0lBRS9CLE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBb0IsRUFBRSxLQUFlLEVBQVEsRUFBRTtRQUMxRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsYUFBYSxDQUFDO1FBQ2pDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNmLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFakIsS0FBSyxNQUFNLFVBQVUsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2xELE1BQU0sZUFBZSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3JELElBQUksZUFBZSxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNoQyxTQUFTO1lBQ2IsQ0FBQztZQUNELElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO2dCQUN2QixNQUFNLEtBQUssR0FBRztvQkFDVixHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztvQkFDekMsVUFBVTtpQkFDYixDQUFDO2dCQUNGLFVBQVUsQ0FBQyxJQUFJLENBQUM7b0JBQ1osS0FBSyxFQUFFLE9BQU87b0JBQ2QsSUFBSSxFQUFFLDBCQUEwQjtvQkFDaEMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO29CQUNwQixLQUFLLEVBQUUsS0FBSyxDQUFDLElBQUk7b0JBQ2pCLElBQUksRUFBRSxLQUFLLENBQUMsUUFBUTtvQkFDcEIsS0FBSyxFQUFFLFdBQVc7b0JBQ2xCLE9BQU8sRUFBRSw4QkFBOEIsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRTtpQkFDOUQsQ0FBQyxDQUFDO1lBQ1AsQ0FBQztpQkFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztnQkFDL0IsS0FBSyxDQUFDLGVBQWUsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNsQyxDQUFDO1FBQ0wsQ0FBQztRQUVELEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNaLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEIsQ0FBQyxDQUFDO0lBRUYsS0FBSyxNQUFNLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDeEMsSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ2pDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDckIsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLFVBQVUsQ0FBQztBQUN0QixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxLQUFZO0lBQ3pDLE1BQU0sVUFBVSxHQUFnQixFQUFFLENBQUM7SUFDbkMsS0FBSyxNQUFNLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzNCLFNBQVM7UUFDYixDQUFDO1FBQ0QsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLENBQUM7UUFDakQsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFDRCxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUM3QyxPQUFPLFVBQVUsQ0FBQztBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgd29ybGQ6IHRoZSBpbi1tZW1vcnkgcmVwcmVzZW50YXRpb24gb2YgYSBsb2FkZWQgZGF0YXNldCByb290LCBwbHVzIHRoZVxuICogdG9wLWxldmVsIHNlbWFudGljLXJ1bGUgcnVubmVyLlxuICpcbiAqIEEgYFdvcmxkYCBob2xkcyBldmVyeSBzY2hlbWEgYW5kIGV2ZXJ5IHRhYmxlIChhcyBhIGNvbmNyZXRlXG4gKiBgVGFibGVUeXBlQmFzZWAgaW5zdGFuY2UpLiBgcnVuU2VtYW50aWNSdWxlc2Agd2Fsa3MgdGhlIHdvcmxkLCBhc2tpbmcgZWFjaFxuICogc3RydWN0dXJhbGx5LXZhbGlkIHRhYmxlIGZvciBpdHMgaW50cmEtdGFibGUgYW5kIGNyb3NzLWZpbGUgdmlvbGF0aW9ucyxcbiAqIHRoZW4gYXBwZW5kcyB0aGUgb25lIGdsb2JhbCBydWxlIHRoYXQgaGFzIHRvIHNlZSB0aGUgd2hvbGUgZ3JhcGggYXQgb25jZVxuICogKGN5Y2xlIGRldGVjdGlvbikuXG4gKi9cblxuaW1wb3J0IHtcbiAgICBTY2hlbWFEZXNjcmlwdGlvbixcbiAgICBWaW9sYXRpb24sXG59IGZyb20gJy4vbW9kZWwnO1xuaW1wb3J0IHR5cGUge1xuICAgIFRhYmxlVHlwZUJhc2UsXG59IGZyb20gJy4vdGFibGUtdHlwZSc7XG5cbi8qKiBBIHNjaGVtYSBsb2FkZWQgZnJvbSBkaXNrLiAqL1xuZXhwb3J0IGludGVyZmFjZSBMb2FkZWRTY2hlbWEge1xuICAgIC8qKiBTY2hlbWEgbmFtZSAodGhlIGZvbGRlciBuYW1lKS4gKi9cbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgICAvKiogQWJzb2x1dGUgcGF0aCB0byB0aGUgc2NoZW1hIGZvbGRlci4gKi9cbiAgICByZWFkb25seSBkaXJQYXRoOiBzdHJpbmc7XG5cbiAgICAvKiogRGVzY3JpcHRpb24gZnJvbSBgPHNjaGVtYT4uanNvbmAsIG9yIG51bGwgaWYgdGhhdCBmaWxlIGlzIG1pc3NpbmcuICovXG4gICAgcmVhZG9ubHkgZGVzY3JpcHRpb246IFNjaGVtYURlc2NyaXB0aW9uIHwgbnVsbDtcblxuICAgIC8qKiBUYWJsZXMgaW4gdGhpcyBzY2hlbWEuICovXG4gICAgcmVhZG9ubHkgdGFibGVzOiBUYWJsZVR5cGVCYXNlW107XG59XG5cbi8qKiBUaGUgd2hvbGUgbG9hZGVkIGRhdGFzZXQgcm9vdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV29ybGQge1xuICAgIC8qKiBBYnNvbHV0ZSBwYXRoIHRvIHRoZSByb290LiAqL1xuICAgIHJlYWRvbmx5IHJvb3REaXI6IHN0cmluZztcblxuICAgIC8qKiBTY2hlbWFzIGtleWVkIGJ5IG5hbWUuICovXG4gICAgcmVhZG9ubHkgc2NoZW1hczogTWFwPHN0cmluZywgTG9hZGVkU2NoZW1hPjtcblxuICAgIC8qKiBUYWJsZXMga2V5ZWQgYnkgYHNjaGVtYS50YWJsZWAuICovXG4gICAgcmVhZG9ubHkgdGFibGVzOiBNYXA8c3RyaW5nLCBUYWJsZVR5cGVCYXNlPjtcbn1cblxuLy8vIERFUEVOREVOQ1lfR1JBUEhfQUNZQ0xJQyDigJQgdGhlIGRlcGVuZHNPbiBncmFwaCBoYXMgbm8gY3ljbGVzLlxuLy8vXG4vLy8gU3RhbmRhcmQgdGhyZWUtY29sb3VyIERGUy4gRWFjaCBiYWNrLWVkZ2UgKGEgZGVwZW5kZW5jeSBwb2ludGluZyBhdCBhIHRhYmxlXG4vLy8gc3RpbGwgb24gdGhlIGN1cnJlbnQgc3RhY2spIGNsb3NlcyBhIGN5Y2xlIGFuZCBpcyBkZXRlY3RlZCBleGFjdGx5IG9uY2UsXG4vLy8gYmVjYXVzZSBldmVyeSB0YWJsZSBpcyBjb2xvdXJlZCBncmV5IHRoZW4gYmxhY2sgYSBzaW5nbGUgdGltZS4gVGhpcyBydWxlXG4vLy8gc3RheXMgYSBmcmVlIGZ1bmN0aW9uIGJlY2F1c2UgaXQgb3BlcmF0ZXMgb24gdGhlIHdob2xlIGdyYXBoIGF0IG9uY2UsIG5vdFxuLy8vIG9uIGFueSBzaW5nbGUgdGFibGUgaW4gaXNvbGF0aW9uLlxuZnVuY3Rpb24gYWN5Y2xpY1Zpb2xhdGlvbnMod29ybGQ6IFdvcmxkKTogVmlvbGF0aW9uW10ge1xuICAgIGNvbnN0IHZpb2xhdGlvbnM6IFZpb2xhdGlvbltdID0gW107XG4gICAgY29uc3Qgd2hpdGUgPSBuZXcgU2V0KHdvcmxkLnRhYmxlcy5rZXlzKCkpO1xuICAgIGNvbnN0IGdyYXkgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAgIGNvbnN0IHZpc2l0ID0gKHRhYmxlOiBUYWJsZVR5cGVCYXNlLCBzdGFjazogc3RyaW5nW10pOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3Qgbm9kZSA9IHRhYmxlLnF1YWxpZmllZE5hbWU7XG4gICAgICAgIHdoaXRlLmRlbGV0ZShub2RlKTtcbiAgICAgICAgZ3JheS5hZGQobm9kZSk7XG4gICAgICAgIHN0YWNrLnB1c2gobm9kZSk7XG5cbiAgICAgICAgZm9yIChjb25zdCBkZXBlbmRlbmN5IG9mIHRhYmxlLmRlZmluaXRpb24uZGVwZW5kc09uKSB7XG4gICAgICAgICAgICBjb25zdCBkZXBlbmRlbmN5VGFibGUgPSB3b3JsZC50YWJsZXMuZ2V0KGRlcGVuZGVuY3kpO1xuICAgICAgICAgICAgaWYgKGRlcGVuZGVuY3lUYWJsZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZ3JheS5oYXMoZGVwZW5kZW5jeSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjeWNsZSA9IFtcbiAgICAgICAgICAgICAgICAgICAgLi4uc3RhY2suc2xpY2Uoc3RhY2suaW5kZXhPZihkZXBlbmRlbmN5KSksXG4gICAgICAgICAgICAgICAgICAgIGRlcGVuZGVuY3ksXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICB2aW9sYXRpb25zLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBsZXZlbDogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgY29kZTogJ0RFUEVOREVOQ1lfR1JBUEhfQUNZQ0xJQycsXG4gICAgICAgICAgICAgICAgICAgIHNjaGVtYTogdGFibGUuc2NoZW1hLFxuICAgICAgICAgICAgICAgICAgICB0YWJsZTogdGFibGUubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgcGF0aDogdGFibGUuZmlsZVBhdGgsXG4gICAgICAgICAgICAgICAgICAgIGZpZWxkOiAnZGVwZW5kc09uJyxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYGRlcGVuZGVuY3kgY3ljbGUgZGV0ZWN0ZWQ6ICR7Y3ljbGUuam9pbignIC0+ICcpfWAsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHdoaXRlLmhhcyhkZXBlbmRlbmN5KSkge1xuICAgICAgICAgICAgICAgIHZpc2l0KGRlcGVuZGVuY3lUYWJsZSwgc3RhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc3RhY2sucG9wKCk7XG4gICAgICAgIGdyYXkuZGVsZXRlKG5vZGUpO1xuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IHRhYmxlIG9mIHdvcmxkLnRhYmxlcy52YWx1ZXMoKSkge1xuICAgICAgICBpZiAod2hpdGUuaGFzKHRhYmxlLnF1YWxpZmllZE5hbWUpKSB7XG4gICAgICAgICAgICB2aXNpdCh0YWJsZSwgW10pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZpb2xhdGlvbnM7XG59XG5cbi8qKlxuICogUnVuIGFsbCBzZW1hbnRpYyBydWxlcyBvdmVyIGEgd29ybGQuXG4gKlxuICogQHBhcmFtIHdvcmxkIFRoZSBsb2FkZWQgZGF0YXNldCByb290LlxuICogQHJldHVybnMgRXZlcnkgc2VtYW50aWMgdmlvbGF0aW9uIGZvdW5kLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuU2VtYW50aWNSdWxlcyh3b3JsZDogV29ybGQpOiBWaW9sYXRpb25bXSB7XG4gICAgY29uc3QgdmlvbGF0aW9uczogVmlvbGF0aW9uW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHRhYmxlIG9mIHdvcmxkLnRhYmxlcy52YWx1ZXMoKSkge1xuICAgICAgICBpZiAoIXRhYmxlLnN0cnVjdHVyYWxseVZhbGlkKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB2aW9sYXRpb25zLnB1c2goLi4udGFibGUuaW50cmFUYWJsZVZpb2xhdGlvbnMoKSk7XG4gICAgICAgIHZpb2xhdGlvbnMucHVzaCguLi50YWJsZS5jcm9zc0ZpbGVWaW9sYXRpb25zKHdvcmxkKSk7XG4gICAgfVxuICAgIHZpb2xhdGlvbnMucHVzaCguLi5hY3ljbGljVmlvbGF0aW9ucyh3b3JsZCkpO1xuICAgIHJldHVybiB2aW9sYXRpb25zO1xufVxuIl19
|