@metaobjectsdev/metadata 1.0.13 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/attr-schema-validate.d.ts.map +1 -1
- package/dist/attr-schema-validate.js +9 -12
- package/dist/attr-schema-validate.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/core/attr/meta-attr-filter.d.ts.map +1 -1
- package/dist/core/attr/meta-attr-filter.js +8 -2
- package/dist/core/attr/meta-attr-filter.js.map +1 -1
- package/dist/core/attr/meta-attr.d.ts +14 -0
- package/dist/core/attr/meta-attr.d.ts.map +1 -1
- package/dist/core/attr/meta-attr.js +23 -1
- package/dist/core/attr/meta-attr.js.map +1 -1
- package/dist/core/field/shared-enum.d.ts +21 -0
- package/dist/core/field/shared-enum.d.ts.map +1 -0
- package/dist/core/field/shared-enum.js +49 -0
- package/dist/core/field/shared-enum.js.map +1 -0
- package/dist/core/identity/meta-identity.d.ts +1 -1
- package/dist/core/identity/meta-identity.d.ts.map +1 -1
- package/dist/core/identity/meta-identity.js +8 -13
- package/dist/core/identity/meta-identity.js.map +1 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/object/object-constants.d.ts +14 -1
- package/dist/core/object/object-constants.d.ts.map +1 -1
- package/dist/core/object/object-constants.js +18 -0
- package/dist/core/object/object-constants.js.map +1 -1
- package/dist/core/object/object-definition.embedded.d.ts.map +1 -1
- package/dist/core/object/object-definition.embedded.js +80 -0
- package/dist/core/object/object-definition.embedded.js.map +1 -1
- package/dist/core/relationship/derive-m2m-fields.d.ts +1 -1
- package/dist/core/relationship/derive-m2m-fields.d.ts.map +1 -1
- package/dist/core/relationship/derive-m2m-fields.js +15 -44
- package/dist/core/relationship/derive-m2m-fields.js.map +1 -1
- package/dist/core/relationship/find-reference.d.ts.map +1 -1
- package/dist/core/relationship/find-reference.js +4 -2
- package/dist/core/relationship/find-reference.js.map +1 -1
- package/dist/core/relationship/resolve-relationship-reference.d.ts +6 -5
- package/dist/core/relationship/resolve-relationship-reference.d.ts.map +1 -1
- package/dist/core/relationship/resolve-relationship-reference.js +9 -7
- package/dist/core/relationship/resolve-relationship-reference.js.map +1 -1
- package/dist/core/reporting/meta-dimension.d.ts +13 -0
- package/dist/core/reporting/meta-dimension.d.ts.map +1 -0
- package/dist/core/reporting/meta-dimension.js +30 -0
- package/dist/core/reporting/meta-dimension.js.map +1 -0
- package/dist/core/reporting/meta-measure.d.ts +24 -0
- package/dist/core/reporting/meta-measure.d.ts.map +1 -0
- package/dist/core/reporting/meta-measure.js +54 -0
- package/dist/core/reporting/meta-measure.js.map +1 -0
- package/dist/core/reporting/meta-segment.d.ts +6 -0
- package/dist/core/reporting/meta-segment.d.ts.map +1 -0
- package/dist/core/reporting/meta-segment.js +13 -0
- package/dist/core/reporting/meta-segment.js.map +1 -0
- package/dist/core/reporting/report-accessors.d.ts +27 -0
- package/dist/core/reporting/report-accessors.d.ts.map +1 -0
- package/dist/core/reporting/report-accessors.js +56 -0
- package/dist/core/reporting/report-accessors.js.map +1 -0
- package/dist/core/reporting/report-describe.d.ts +59 -0
- package/dist/core/reporting/report-describe.d.ts.map +1 -0
- package/dist/core/reporting/report-describe.js +182 -0
- package/dist/core/reporting/report-describe.js.map +1 -0
- package/dist/core/reporting/report-read-model.d.ts +34 -0
- package/dist/core/reporting/report-read-model.d.ts.map +1 -0
- package/dist/core/reporting/report-read-model.js +165 -0
- package/dist/core/reporting/report-read-model.js.map +1 -0
- package/dist/core/reporting/report-shape.d.ts +103 -0
- package/dist/core/reporting/report-shape.d.ts.map +1 -0
- package/dist/core/reporting/report-shape.js +398 -0
- package/dist/core/reporting/report-shape.js.map +1 -0
- package/dist/core/reporting/reporting-constants.d.ts +65 -0
- package/dist/core/reporting/reporting-constants.d.ts.map +1 -0
- package/dist/core/reporting/reporting-constants.js +84 -0
- package/dist/core/reporting/reporting-constants.js.map +1 -0
- package/dist/core/reporting/reporting-definition.embedded.d.ts +3 -0
- package/dist/core/reporting/reporting-definition.embedded.d.ts.map +1 -0
- package/dist/core/reporting/reporting-definition.embedded.js +185 -0
- package/dist/core/reporting/reporting-definition.embedded.js.map +1 -0
- package/dist/core/requirement/resolve-claim.d.ts +8 -0
- package/dist/core/requirement/resolve-claim.d.ts.map +1 -1
- package/dist/core/requirement/resolve-claim.js +21 -0
- package/dist/core/requirement/resolve-claim.js.map +1 -1
- package/dist/core/yaml-desugar.d.ts.map +1 -1
- package/dist/core/yaml-desugar.js +12 -82
- package/dist/core/yaml-desugar.js.map +1 -1
- package/dist/core-types.d.ts.map +1 -1
- package/dist/core-types.js +28 -1
- package/dist/core-types.js.map +1 -1
- package/dist/docs-ref.d.ts +19 -0
- package/dist/docs-ref.d.ts.map +1 -0
- package/dist/docs-ref.js +37 -0
- package/dist/docs-ref.js.map +1 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +17 -6
- package/dist/errors.js.map +1 -1
- package/dist/fmt.d.ts.map +1 -1
- package/dist/fmt.js +3 -1
- package/dist/fmt.js.map +1 -1
- package/dist/index.d.ts +15 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -4
- package/dist/index.js.map +1 -1
- package/dist/loader/declared-duplicate-fields.d.ts +19 -0
- package/dist/loader/declared-duplicate-fields.d.ts.map +1 -0
- package/dist/loader/declared-duplicate-fields.js +97 -0
- package/dist/loader/declared-duplicate-fields.js.map +1 -0
- package/dist/loader/meta-data-loader.d.ts.map +1 -1
- package/dist/loader/meta-data-loader.js +18 -1
- package/dist/loader/meta-data-loader.js.map +1 -1
- package/dist/loader/reporting-validation.d.ts +11 -0
- package/dist/loader/reporting-validation.d.ts.map +1 -0
- package/dist/loader/reporting-validation.js +883 -0
- package/dist/loader/reporting-validation.js.map +1 -0
- package/dist/loader/resolve-references.d.ts +8 -0
- package/dist/loader/resolve-references.d.ts.map +1 -0
- package/dist/loader/resolve-references.js +132 -0
- package/dist/loader/resolve-references.js.map +1 -0
- package/dist/loader/validation-passes.d.ts.map +1 -1
- package/dist/loader/validation-passes.js +14 -9
- package/dist/loader/validation-passes.js.map +1 -1
- package/dist/loader/validation-registry.d.ts.map +1 -1
- package/dist/loader/validation-registry.js +33 -10
- package/dist/loader/validation-registry.js.map +1 -1
- package/dist/metamodel-docs/index.js +3 -3
- package/dist/metamodel-docs/index.js.map +1 -1
- package/dist/metamodel-docs/render.js +4 -4
- package/dist/metamodel-docs/render.js.map +1 -1
- package/dist/naming-refs.d.ts +102 -50
- package/dist/naming-refs.d.ts.map +1 -1
- package/dist/naming-refs.js +223 -97
- package/dist/naming-refs.js.map +1 -1
- package/dist/naming.d.ts +42 -7
- package/dist/naming.d.ts.map +1 -1
- package/dist/naming.js +43 -5
- package/dist/naming.js.map +1 -1
- package/dist/object-serializer.d.ts.map +1 -1
- package/dist/object-serializer.js +6 -9
- package/dist/object-serializer.js.map +1 -1
- package/dist/parser-core.d.ts.map +1 -1
- package/dist/parser-core.js +18 -48
- package/dist/parser-core.js.map +1 -1
- package/dist/persistence/db/db-definition.embedded.js +2 -2
- package/dist/persistence/db/db-definition.embedded.js.map +1 -1
- package/dist/persistence/source/meta-source.d.ts +5 -3
- package/dist/persistence/source/meta-source.d.ts.map +1 -1
- package/dist/persistence/source/meta-source.js +8 -6
- package/dist/persistence/source/meta-source.js.map +1 -1
- package/dist/registry-manifest-exclusions.js +2 -2
- package/dist/registry-manifest-exclusions.js.map +1 -1
- package/dist/registry-manifest.d.ts +1 -1
- package/dist/registry-manifest.js +1 -1
- package/dist/release-docs.d.ts +11 -0
- package/dist/release-docs.d.ts.map +1 -0
- package/dist/release-docs.js +48 -0
- package/dist/release-docs.js.map +1 -0
- package/dist/serializer-json.d.ts +15 -1
- package/dist/serializer-json.d.ts.map +1 -1
- package/dist/serializer-json.js +55 -17
- package/dist/serializer-json.js.map +1 -1
- package/dist/shared/base-types.d.ts +7 -1
- package/dist/shared/base-types.d.ts.map +1 -1
- package/dist/shared/base-types.js +9 -0
- package/dist/shared/base-types.js.map +1 -1
- package/dist/shared/meta-data.d.ts +10 -0
- package/dist/shared/meta-data.d.ts.map +1 -1
- package/dist/shared/meta-data.js +22 -1
- package/dist/shared/meta-data.js.map +1 -1
- package/dist/shared/meta-root.d.ts +13 -1
- package/dist/shared/meta-root.d.ts.map +1 -1
- package/dist/shared/meta-root.js +19 -1
- package/dist/shared/meta-root.js.map +1 -1
- package/dist/super-resolve.d.ts +4 -1
- package/dist/super-resolve.d.ts.map +1 -1
- package/dist/super-resolve.js +44 -65
- package/dist/super-resolve.js.map +1 -1
- package/dist/vocabulary-catalog.js +2 -2
- package/dist/vocabulary-catalog.js.map +1 -1
- package/package.json +6 -1
- package/src/attr-schema-validate.ts +9 -13
- package/src/constants.ts +1 -0
- package/src/core/attr/meta-attr-filter.ts +8 -1
- package/src/core/attr/meta-attr.ts +24 -1
- package/src/core/field/shared-enum.ts +53 -0
- package/src/core/identity/meta-identity.ts +9 -12
- package/src/core/index.ts +5 -0
- package/src/core/object/object-constants.ts +19 -0
- package/src/core/object/object-definition.embedded.ts +80 -0
- package/src/core/relationship/derive-m2m-fields.ts +15 -48
- package/src/core/relationship/find-reference.ts +4 -2
- package/src/core/relationship/resolve-relationship-reference.ts +11 -9
- package/src/core/reporting/meta-dimension.ts +41 -0
- package/src/core/reporting/meta-measure.ts +75 -0
- package/src/core/reporting/meta-segment.ts +14 -0
- package/src/core/reporting/report-accessors.ts +73 -0
- package/src/core/reporting/report-describe.ts +206 -0
- package/src/core/reporting/report-read-model.ts +177 -0
- package/src/core/reporting/report-shape.ts +493 -0
- package/src/core/reporting/reporting-constants.ts +104 -0
- package/src/core/reporting/reporting-definition.embedded.ts +192 -0
- package/src/core/requirement/resolve-claim.ts +20 -0
- package/src/core/yaml-desugar.ts +9 -89
- package/src/core-types.ts +41 -0
- package/src/docs-ref.ts +41 -0
- package/src/errors.ts +17 -6
- package/src/fmt.ts +3 -1
- package/src/index.ts +72 -4
- package/src/loader/declared-duplicate-fields.ts +114 -0
- package/src/loader/meta-data-loader.ts +25 -1
- package/src/loader/reporting-validation.ts +1137 -0
- package/src/loader/resolve-references.ts +144 -0
- package/src/loader/validation-passes.ts +13 -9
- package/src/loader/validation-registry.ts +37 -9
- package/src/metamodel-docs/index.ts +3 -3
- package/src/metamodel-docs/render.ts +4 -4
- package/src/naming-refs.ts +237 -94
- package/src/naming.ts +75 -11
- package/src/object-serializer.ts +7 -9
- package/src/parser-core.ts +19 -56
- package/src/persistence/db/db-definition.embedded.ts +2 -2
- package/src/persistence/source/meta-source.ts +8 -6
- package/src/registry-manifest-exclusions.ts +2 -2
- package/src/registry-manifest.ts +1 -1
- package/src/release-docs.ts +48 -0
- package/src/serializer-json.ts +79 -12
- package/src/shared/base-types.ts +9 -0
- package/src/shared/meta-data.ts +22 -1
- package/src/shared/meta-root.ts +20 -1
- package/src/super-resolve.ts +49 -63
- package/src/vocabulary-catalog.ts +2 -2
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Free accessors over an `object.report` node (FR-044). Used by the Plan 2
|
|
2
|
+
// lowering and by the loader's report validation, so the `name:grain` parse and
|
|
3
|
+
// the derived-field-name rule have exactly one definition.
|
|
4
|
+
import { OBJECT_REPORT_ATTR_DIMENSIONS, OBJECT_REPORT_ATTR_FROM, OBJECT_REPORT_ATTR_MEASURES, OBJECT_REPORT_ATTR_SPINE, } from "../object/object-constants.js";
|
|
5
|
+
import { CHILD_REF_SEPARATOR } from "../../shared/structural.js";
|
|
6
|
+
import { REPORT_DIMENSION_GRAIN_SEPARATOR } from "./reporting-constants.js";
|
|
7
|
+
function stringList(v) {
|
|
8
|
+
if (Array.isArray(v))
|
|
9
|
+
return v.filter((x) => typeof x === "string");
|
|
10
|
+
return typeof v === "string" ? [v] : [];
|
|
11
|
+
}
|
|
12
|
+
/** The `@from` entity name of a report. */
|
|
13
|
+
export function reportFrom(obj) {
|
|
14
|
+
const v = obj.attr(OBJECT_REPORT_ATTR_FROM);
|
|
15
|
+
return typeof v === "string" ? v : undefined;
|
|
16
|
+
}
|
|
17
|
+
/** `@spine`: the to-one path to the entity whose rows supply the report's rows. */
|
|
18
|
+
export function reportSpine(obj) {
|
|
19
|
+
const v = obj.attr(OBJECT_REPORT_ATTR_SPINE);
|
|
20
|
+
return typeof v === "string" && v !== "" ? v : undefined;
|
|
21
|
+
}
|
|
22
|
+
/** The `@dimensions` items, each `name` or `name:grain`. */
|
|
23
|
+
export function reportDimensionItems(obj) {
|
|
24
|
+
return stringList(obj.attr(OBJECT_REPORT_ATTR_DIMENSIONS)).map((raw) => {
|
|
25
|
+
const i = raw.indexOf(REPORT_DIMENSION_GRAIN_SEPARATOR);
|
|
26
|
+
return i === -1 ? { name: raw } : { name: raw.slice(0, i), grain: raw.slice(i + 1) };
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** The `@measures` items AS WRITTEN: each a bare measure `name`, or a dotted
|
|
30
|
+
* `Entity.name` (loader rule R3). Use {@link reportMeasureItemName} for the measure name. */
|
|
31
|
+
export function reportMeasureNames(obj) {
|
|
32
|
+
return stringList(obj.attr(OBJECT_REPORT_ATTR_MEASURES));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The measure a `@measures` item names: the segment after its LAST `.`
|
|
36
|
+
* (`total`, `Sale.total` and `acme::shop::Sale.total` all name `total`). It is also
|
|
37
|
+
* the derived report field's name. The part before that `.`, when present, is an
|
|
38
|
+
* entity qualifier, which {@link reportMeasureItemOwner} returns.
|
|
39
|
+
*/
|
|
40
|
+
export function reportMeasureItemName(item) {
|
|
41
|
+
const dot = item.lastIndexOf(CHILD_REF_SEPARATOR);
|
|
42
|
+
return dot === -1 ? item : item.slice(dot + CHILD_REF_SEPARATOR.length);
|
|
43
|
+
}
|
|
44
|
+
/** The entity qualifier of a dotted `@measures` item (`Sale` in `Sale.total`), or
|
|
45
|
+
* undefined for a bare item. Loader rule R3: it names `@from` or an entity `@from` extends. */
|
|
46
|
+
export function reportMeasureItemOwner(item) {
|
|
47
|
+
const dot = item.lastIndexOf(CHILD_REF_SEPARATOR);
|
|
48
|
+
return dot === -1 ? undefined : item.slice(0, dot);
|
|
49
|
+
}
|
|
50
|
+
/** The derived report field for a dimension item: `name` (attribute) or `name` + Capitalized(grain) (time). */
|
|
51
|
+
export function reportDerivedFieldName(item) {
|
|
52
|
+
if (item.grain === undefined || item.grain === "")
|
|
53
|
+
return item.name;
|
|
54
|
+
return item.name + item.grain.charAt(0).toUpperCase() + item.grain.slice(1);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=report-accessors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-accessors.js","sourceRoot":"","sources":["../../../src/core/reporting/report-accessors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { MetaData } from "../../shared/meta-data.js";
|
|
2
|
+
import type { MetaRoot } from "../../shared/meta-root.js";
|
|
3
|
+
import type { MetaObject } from "../object/meta-object.js";
|
|
4
|
+
import { type ReportField, type ReportShape } from "./report-shape.js";
|
|
5
|
+
/** A row-scope filter as the loader holds it: compact JSON in declared order, in a code span. */
|
|
6
|
+
export declare function describeFilter(filter: unknown): string;
|
|
7
|
+
/**
|
|
8
|
+
* "segment `paid` and filter `{…}`": the rows a measure or a report is scoped to, or
|
|
9
|
+
* undefined when it declares neither. The two combine by AND, as the lowering combines them.
|
|
10
|
+
*/
|
|
11
|
+
export declare function describeRowScope(segment: unknown, filter: unknown): string | undefined;
|
|
12
|
+
/** A dimension as its entity declares it: the column, and for a time dimension its grains. */
|
|
13
|
+
export declare function describeDimension(dim: MetaData): string;
|
|
14
|
+
/**
|
|
15
|
+
* A dimension as ONE report column. A time dimension is truncated to the grain the report
|
|
16
|
+
* picked; reports are UTC only (there is no time-zone vocabulary). After a `via` clause
|
|
17
|
+
* the truncation is set off by a comma, so it reads as applying to the column and not to
|
|
18
|
+
* the relationship path.
|
|
19
|
+
*/
|
|
20
|
+
export declare function describeDimensionColumn(dim: MetaData, grain?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* A measure in words: the aggregate and its row scope, or the ratio and its null rule. A
|
|
23
|
+
* `@default` ends either with the value it reads when there is nothing to aggregate; a
|
|
24
|
+
* defaulted ratio is never null, so its null rule gives way to that clause.
|
|
25
|
+
*/
|
|
26
|
+
export declare function describeMeasure(measure: MetaData): string;
|
|
27
|
+
/** A segment in words: its filter. */
|
|
28
|
+
export declare function describeSegment(segment: MetaData): string;
|
|
29
|
+
/** One derived report column's definition, from the dimension or measure it comes from. */
|
|
30
|
+
export declare function describeReportField(field: ReportField): string;
|
|
31
|
+
/**
|
|
32
|
+
* Where a report with `@spine` takes its rows (R8): "one row per distinct dimension tuple
|
|
33
|
+
* among the rows of `Program`, reached by `Purchase.program`, including those no `Purchase`
|
|
34
|
+
* refers to". Undefined for a report without `@spine`, whose rows are the groups of its
|
|
35
|
+
* `@from` rows and need no sentence. The spine is printed as declared.
|
|
36
|
+
*/
|
|
37
|
+
export declare function describeReportRows(shape: ReportShape, root: MetaRoot): string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* A report's row scope ({@link describeRowScope} over its `@segment` and `@filter`), or
|
|
40
|
+
* undefined when it declares neither. Under `@spine` the scope chooses which rows of `@from`
|
|
41
|
+
* are aggregated and never removes a row of the report, so it reads "aggregating only
|
|
42
|
+
* segment `paid`".
|
|
43
|
+
*/
|
|
44
|
+
export declare function describeReportRowScope(report: MetaObject): string | undefined;
|
|
45
|
+
/** The neutral logical type of a derived column: its Table B subtype, `[]` for an array. */
|
|
46
|
+
export declare function reportFieldTypeName(field: ReportField): string;
|
|
47
|
+
/**
|
|
48
|
+
* Why a report is not served, or undefined when it is. The loader refuses an abstract
|
|
49
|
+
* report (R11) and a read source whose `@kind` is not `view` (R10), so the one way a loaded
|
|
50
|
+
* report goes unserved is declaring no read source at all (Plan 3 Table A).
|
|
51
|
+
*/
|
|
52
|
+
export declare function reportNotServedReason(report: MetaObject): string | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* The attributes the describer for `node` reads, so a documentation coverage audit can
|
|
55
|
+
* mark exactly those as rendered and no others. Kept beside the describers: a describer
|
|
56
|
+
* that starts reading a new attribute adds it here. Empty for any other node.
|
|
57
|
+
*/
|
|
58
|
+
export declare function reportingDescribedAttrs(node: MetaData): readonly string[];
|
|
59
|
+
//# sourceMappingURL=report-describe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-describe.d.ts","sourceRoot":"","sources":["../../../src/core/reporting/report-describe.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAG1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAkB3D,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAY1F,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAEtD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKtF;AAaD,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAIvD;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7E;AAWD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,CAkBzD;AAED,sCAAsC;AACtC,wBAAgB,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,CAEzD;AAED,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAG9D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAUzF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAK7E;AAED,4FAA4F;AAC5F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAG9D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAE5E;AAWD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,MAAM,EAAE,CAKzE"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// The reporting vocabulary in words (FR-044): what a dimension groups by, what a measure
|
|
2
|
+
// computes, which rows a segment or report is scoped to, and why a report is not served.
|
|
3
|
+
//
|
|
4
|
+
// One home for the wording. The docs generators print these sentences on the markdown model pages
|
|
5
|
+
// (codegen-ts) and on the HTML site (docs-site); both read them from here, so the two
|
|
6
|
+
// surfaces cannot say different things about the same node.
|
|
7
|
+
//
|
|
8
|
+
// Every function returns PLAIN TEXT whose identifiers sit in single-backtick spans
|
|
9
|
+
// ("sum of `Invoice.amountCents` where segment `paid`"). A caller turns the spans into
|
|
10
|
+
// its own markup. Nothing here derives SQL: a description says what a column means, never
|
|
11
|
+
// how the view computes it.
|
|
12
|
+
//
|
|
13
|
+
// Browser-safe: no Node-only import.
|
|
14
|
+
import { TYPE_DIMENSION, TYPE_MEASURE, TYPE_SEGMENT } from "../../shared/base-types.js";
|
|
15
|
+
import { AGG_ALL } from "../../persistence/origin/origin-constants.js";
|
|
16
|
+
import { OBJECT_REPORT_ATTR_FILTER, OBJECT_REPORT_ATTR_SEGMENT, OBJECT_REPORT_ATTR_SPINE } from "../object/object-constants.js";
|
|
17
|
+
import { DIMENSION_SUBTYPE_TIME, MEASURE_SUBTYPE_RATIO, REPORTING_ATTR_AGG, REPORTING_ATTR_DEFAULT, REPORTING_ATTR_DENOMINATOR, REPORTING_ATTR_DISTINCT, REPORTING_ATTR_FILTER, REPORTING_ATTR_GRAINS, REPORTING_ATTR_NUMERATOR, REPORTING_ATTR_OF, REPORTING_ATTR_SEGMENT, REPORTING_ATTR_VIA, } from "./reporting-constants.js";
|
|
18
|
+
import { reportSpine } from "./report-accessors.js";
|
|
19
|
+
import { reportReadSource } from "./report-read-model.js";
|
|
20
|
+
import { reportSpineEntity } from "./report-shape.js";
|
|
21
|
+
/** Inline code. A backtick cannot sit inside a single-backtick span, so it is dropped. */
|
|
22
|
+
function tick(text) {
|
|
23
|
+
return `\`${text.replace(/`/g, "")}\``;
|
|
24
|
+
}
|
|
25
|
+
function stringList(v) {
|
|
26
|
+
if (Array.isArray(v))
|
|
27
|
+
return v.filter((x) => typeof x === "string");
|
|
28
|
+
return typeof v === "string" ? [v] : [];
|
|
29
|
+
}
|
|
30
|
+
/** A row-scope filter as the loader holds it: compact JSON in declared order, in a code span. */
|
|
31
|
+
export function describeFilter(filter) {
|
|
32
|
+
return tick(JSON.stringify(filter ?? {}));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* "segment `paid` and filter `{…}`": the rows a measure or a report is scoped to, or
|
|
36
|
+
* undefined when it declares neither. The two combine by AND, as the lowering combines them.
|
|
37
|
+
*/
|
|
38
|
+
export function describeRowScope(segment, filter) {
|
|
39
|
+
const parts = [];
|
|
40
|
+
if (typeof segment === "string" && segment !== "")
|
|
41
|
+
parts.push(`segment ${tick(segment)}`);
|
|
42
|
+
if (filter !== undefined && filter !== null)
|
|
43
|
+
parts.push(`filter ${describeFilter(filter)}`);
|
|
44
|
+
return parts.length > 0 ? parts.join(" and ") : undefined;
|
|
45
|
+
}
|
|
46
|
+
/** "`Program.title` via `Purchase.program`": the column a dimension groups by. */
|
|
47
|
+
function dimensionColumn(dim) {
|
|
48
|
+
// ADR-0039: resolving reads, here and in every describer below, so a node that
|
|
49
|
+
// `extends` another is described by its effective attributes. References are
|
|
50
|
+
// printed as the author wrote them (ADR-0059), not as the loader resolved them.
|
|
51
|
+
const of = dim.authoredAttr(REPORTING_ATTR_OF);
|
|
52
|
+
const via = dim.authoredAttr(REPORTING_ATTR_VIA);
|
|
53
|
+
const column = tick(typeof of === "string" ? of : "");
|
|
54
|
+
return typeof via === "string" && via !== "" ? `${column} via ${tick(via)}` : column;
|
|
55
|
+
}
|
|
56
|
+
/** A dimension as its entity declares it: the column, and for a time dimension its grains. */
|
|
57
|
+
export function describeDimension(dim) {
|
|
58
|
+
const column = dimensionColumn(dim);
|
|
59
|
+
if (dim.subType !== DIMENSION_SUBTYPE_TIME)
|
|
60
|
+
return column;
|
|
61
|
+
return `${column}; grains: ${stringList(dim.attr(REPORTING_ATTR_GRAINS)).join(", ")}`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A dimension as ONE report column. A time dimension is truncated to the grain the report
|
|
65
|
+
* picked; reports are UTC only (there is no time-zone vocabulary). After a `via` clause
|
|
66
|
+
* the truncation is set off by a comma, so it reads as applying to the column and not to
|
|
67
|
+
* the relationship path.
|
|
68
|
+
*/
|
|
69
|
+
export function describeDimensionColumn(dim, grain) {
|
|
70
|
+
const column = dimensionColumn(dim);
|
|
71
|
+
if (grain === undefined || grain === "")
|
|
72
|
+
return column;
|
|
73
|
+
const joiner = column.includes(" via ") ? "," : "";
|
|
74
|
+
return `${column}${joiner} truncated to ${grain}, UTC`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* "; `0` when there is nothing to aggregate": the clause a measure's `@default` adds (R9), or
|
|
78
|
+
* "" when it declares none. The declared integer is printed as written.
|
|
79
|
+
*/
|
|
80
|
+
function defaultClause(measure) {
|
|
81
|
+
const declared = measure.attr(REPORTING_ATTR_DEFAULT);
|
|
82
|
+
return typeof declared === "number" ? `; ${tick(String(declared))} when there is nothing to aggregate` : "";
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A measure in words: the aggregate and its row scope, or the ratio and its null rule. A
|
|
86
|
+
* `@default` ends either with the value it reads when there is nothing to aggregate; a
|
|
87
|
+
* defaulted ratio is never null, so its null rule gives way to that clause.
|
|
88
|
+
*/
|
|
89
|
+
export function describeMeasure(measure) {
|
|
90
|
+
const fallback = defaultClause(measure);
|
|
91
|
+
if (measure.subType === MEASURE_SUBTYPE_RATIO) {
|
|
92
|
+
const numerator = measure.attr(REPORTING_ATTR_NUMERATOR);
|
|
93
|
+
const denominator = measure.attr(REPORTING_ATTR_DENOMINATOR);
|
|
94
|
+
const quotient = `${tick(String(numerator ?? ""))} / ${tick(String(denominator ?? ""))}`;
|
|
95
|
+
return fallback !== "" ? `${quotient}${fallback}` : `${quotient}, null when the denominator is 0`;
|
|
96
|
+
}
|
|
97
|
+
const columns = stringList(measure.authoredAttr(REPORTING_ATTR_OF)).map(tick);
|
|
98
|
+
const scope = describeRowScope(measure.attr(REPORTING_ATTR_SEGMENT), measure.attr(REPORTING_ATTR_FILTER));
|
|
99
|
+
if (columns.length === 0) {
|
|
100
|
+
// @agg any / all with no @of (loader rule M0): the row condition is the quantified predicate.
|
|
101
|
+
const quantifier = measure.attr(REPORTING_ATTR_AGG) === AGG_ALL ? "every row" : "some row";
|
|
102
|
+
return `true when ${quantifier} has ${scope ?? ""}${fallback}`;
|
|
103
|
+
}
|
|
104
|
+
const of = columns.length === 1 ? columns[0] : `(${columns.join(", ")})`;
|
|
105
|
+
const distinct = measure.attr(REPORTING_ATTR_DISTINCT) === true ? "distinct " : "";
|
|
106
|
+
return `${String(measure.attr(REPORTING_ATTR_AGG) ?? "")} of ${distinct}${of}${scope !== undefined ? ` where ${scope}` : ""}${fallback}`;
|
|
107
|
+
}
|
|
108
|
+
/** A segment in words: its filter. */
|
|
109
|
+
export function describeSegment(segment) {
|
|
110
|
+
return describeFilter(segment.attr(REPORTING_ATTR_FILTER));
|
|
111
|
+
}
|
|
112
|
+
/** One derived report column's definition, from the dimension or measure it comes from. */
|
|
113
|
+
export function describeReportField(field) {
|
|
114
|
+
if (field.dimension !== undefined)
|
|
115
|
+
return describeDimensionColumn(field.dimension, field.grain);
|
|
116
|
+
return field.measure !== undefined ? describeMeasure(field.measure) : "";
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Where a report with `@spine` takes its rows (R8): "one row per distinct dimension tuple
|
|
120
|
+
* among the rows of `Program`, reached by `Purchase.program`, including those no `Purchase`
|
|
121
|
+
* refers to". Undefined for a report without `@spine`, whose rows are the groups of its
|
|
122
|
+
* `@from` rows and need no sentence. The spine is printed as declared.
|
|
123
|
+
*/
|
|
124
|
+
export function describeReportRows(shape, root) {
|
|
125
|
+
const entity = reportSpineEntity(shape.report, shape.from, root);
|
|
126
|
+
// Printed as the author wrote it (ADR-0059).
|
|
127
|
+
const authored = reportSpine(shape.report) !== undefined ? shape.report.authoredAttr(OBJECT_REPORT_ATTR_SPINE) : undefined;
|
|
128
|
+
const spine = typeof authored === "string" ? authored : undefined;
|
|
129
|
+
if (spine === undefined || entity === undefined)
|
|
130
|
+
return undefined;
|
|
131
|
+
return (`one row per distinct dimension tuple among the rows of ${tick(entity.name)}, reached by ${tick(spine)}, ` +
|
|
132
|
+
`including those no ${tick(shape.from.name)} refers to`);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* A report's row scope ({@link describeRowScope} over its `@segment` and `@filter`), or
|
|
136
|
+
* undefined when it declares neither. Under `@spine` the scope chooses which rows of `@from`
|
|
137
|
+
* are aggregated and never removes a row of the report, so it reads "aggregating only
|
|
138
|
+
* segment `paid`".
|
|
139
|
+
*/
|
|
140
|
+
export function describeReportRowScope(report) {
|
|
141
|
+
// ADR-0039: resolving.
|
|
142
|
+
const scope = describeRowScope(report.attr(OBJECT_REPORT_ATTR_SEGMENT), report.attr(OBJECT_REPORT_ATTR_FILTER));
|
|
143
|
+
if (scope === undefined)
|
|
144
|
+
return undefined;
|
|
145
|
+
return reportSpine(report) !== undefined ? `aggregating only ${scope}` : scope;
|
|
146
|
+
}
|
|
147
|
+
/** The neutral logical type of a derived column: its Table B subtype, `[]` for an array. */
|
|
148
|
+
export function reportFieldTypeName(field) {
|
|
149
|
+
// ADR-0039: resolvedIsArray() is the resolving read of the native array flag.
|
|
150
|
+
return field.typeSource?.resolvedIsArray() === true ? `${field.subType}[]` : field.subType;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Why a report is not served, or undefined when it is. The loader refuses an abstract
|
|
154
|
+
* report (R11) and a read source whose `@kind` is not `view` (R10), so the one way a loaded
|
|
155
|
+
* report goes unserved is declaring no read source at all (Plan 3 Table A).
|
|
156
|
+
*/
|
|
157
|
+
export function reportNotServedReason(report) {
|
|
158
|
+
return reportReadSource(report) === undefined ? "Not served: declares no view source" : undefined;
|
|
159
|
+
}
|
|
160
|
+
const DIMENSION_ATTRS = [REPORTING_ATTR_OF, REPORTING_ATTR_VIA];
|
|
161
|
+
const TIME_DIMENSION_ATTRS = [...DIMENSION_ATTRS, REPORTING_ATTR_GRAINS];
|
|
162
|
+
const AGGREGATE_ATTRS = [
|
|
163
|
+
REPORTING_ATTR_AGG, REPORTING_ATTR_OF, REPORTING_ATTR_DISTINCT, REPORTING_ATTR_SEGMENT, REPORTING_ATTR_FILTER,
|
|
164
|
+
REPORTING_ATTR_DEFAULT,
|
|
165
|
+
];
|
|
166
|
+
const RATIO_ATTRS = [REPORTING_ATTR_NUMERATOR, REPORTING_ATTR_DENOMINATOR, REPORTING_ATTR_DEFAULT];
|
|
167
|
+
const SEGMENT_ATTRS = [REPORTING_ATTR_FILTER];
|
|
168
|
+
/**
|
|
169
|
+
* The attributes the describer for `node` reads, so a documentation coverage audit can
|
|
170
|
+
* mark exactly those as rendered and no others. Kept beside the describers: a describer
|
|
171
|
+
* that starts reading a new attribute adds it here. Empty for any other node.
|
|
172
|
+
*/
|
|
173
|
+
export function reportingDescribedAttrs(node) {
|
|
174
|
+
if (node.type === TYPE_DIMENSION)
|
|
175
|
+
return node.subType === DIMENSION_SUBTYPE_TIME ? TIME_DIMENSION_ATTRS : DIMENSION_ATTRS;
|
|
176
|
+
if (node.type === TYPE_MEASURE)
|
|
177
|
+
return node.subType === MEASURE_SUBTYPE_RATIO ? RATIO_ATTRS : AGGREGATE_ATTRS;
|
|
178
|
+
if (node.type === TYPE_SEGMENT)
|
|
179
|
+
return SEGMENT_ATTRS;
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=report-describe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-describe.js","sourceRoot":"","sources":["../../../src/core/reporting/report-describe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { MetaRoot } from "../../shared/meta-root.js";
|
|
2
|
+
import { MetaSource } from "../../persistence/source/meta-source.js";
|
|
3
|
+
import { MetaObject } from "../object/meta-object.js";
|
|
4
|
+
/**
|
|
5
|
+
* The source a report is READ from: its own read-only source with `@role: primary`,
|
|
6
|
+
* else its first own read-only source. Undefined when it declares none (Table A:
|
|
7
|
+
* not lowered, not served).
|
|
8
|
+
*
|
|
9
|
+
* This is the rule that NAMES the lowered view — `viewName` / `projectionViewSource`
|
|
10
|
+
* in codegen-ts's `projection/extract-view-spec.ts`, reached for a report through
|
|
11
|
+
* `projectionViewName`. It is restated here because the metadata package cannot
|
|
12
|
+
* depend on a codegen package; the two must stay the same rule, or the runtime
|
|
13
|
+
* reads a relation the lowering did not create.
|
|
14
|
+
*
|
|
15
|
+
* What the loader permits, measured: a report may declare several read-only sources
|
|
16
|
+
* (a `@role: replica` view beside its primary view loads clean, in either order);
|
|
17
|
+
* `@role` defaults to `primary`; a report whose sources include no primary is
|
|
18
|
+
* `ERR_SOURCE_NO_PRIMARY` and a writable source on a report is refused. So for every
|
|
19
|
+
* model that loads, the primary branch fires. The first-read-only fallback covers a
|
|
20
|
+
* tree built in code, and keeps this rule identical to the lowering's.
|
|
21
|
+
*/
|
|
22
|
+
export declare function reportReadSource(report: MetaObject): MetaSource | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The read model of an `object.report`: one field per Table B row, in Table B
|
|
25
|
+
* order, plus a copy of the source the report is read from (see
|
|
26
|
+
* `reportReadSource`) when it declares one (Table A). A sourceless report yields a model with no source: it has a shape
|
|
27
|
+
* and no view, and the caller decides what that means (the runtime refuses to
|
|
28
|
+
* serve it).
|
|
29
|
+
*
|
|
30
|
+
* Cached per report node; the model is frozen. Throws what `reportShape` throws
|
|
31
|
+
* when a reference does not resolve.
|
|
32
|
+
*/
|
|
33
|
+
export declare function reportReadModel(report: MetaObject, root: MetaRoot): MetaObject;
|
|
34
|
+
//# sourceMappingURL=report-read-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-read-model.d.ts","sourceRoot":"","sources":["../../../src/core/reporting/report-read-model.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,MAAM,yCAAyC,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AA0EtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAK3E;AAsBD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,GAAG,UAAU,CAgB9E"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// A report's READ MODEL (FR-044): a detached object carrying one real `field.*`
|
|
2
|
+
// child per derived field (Table B) and a copy of the report's own read-only source.
|
|
3
|
+
//
|
|
4
|
+
// WHY IT EXISTS
|
|
5
|
+
//
|
|
6
|
+
// An `object.report` declares no fields: its read shape is derived from its
|
|
7
|
+
// dimensions and measures. A metadata-driven runtime walks an object's field
|
|
8
|
+
// children in a dozen places (column list, filter and sort resolution, the name
|
|
9
|
+
// map, every read coercion). Rather than teach each of them what a report is, the
|
|
10
|
+
// runtime reads a report through this model and sees ordinary fields.
|
|
11
|
+
//
|
|
12
|
+
// WHY IT IS DETACHED
|
|
13
|
+
//
|
|
14
|
+
// The model is never added to the root: it has no parent, `root.objects()` does
|
|
15
|
+
// not list it, and the canonical serializer, `fmt`, codegen and every other tree
|
|
16
|
+
// walker never see it. Nothing in the loaded tree is mutated to build it; in
|
|
17
|
+
// particular the report's own source node is COPIED, not re-parented
|
|
18
|
+
// (`addChild` rewrites the child's parent). The nodes are constructed directly,
|
|
19
|
+
// not through the registry, so the sealed registry is not involved and no
|
|
20
|
+
// vocabulary is added: every node is an already-registered `type.subType`.
|
|
21
|
+
//
|
|
22
|
+
// It keeps the report's name, package and `object.report` subtype, so a consumer
|
|
23
|
+
// holding it can still tell it is a report (no identity, read-only).
|
|
24
|
+
import { TypeId } from "../../registry.js";
|
|
25
|
+
import { TYPE_FIELD } from "../../shared/base-types.js";
|
|
26
|
+
import { isReadOnlySource } from "../../shared/node-guards.js";
|
|
27
|
+
import { MetaSource } from "../../persistence/source/meta-source.js";
|
|
28
|
+
import { SOURCE_ATTR_ROLE, SOURCE_ROLE_PRIMARY } from "../../persistence/source/source-constants.js";
|
|
29
|
+
import { FIELD_ATTR_DB_COLUMN_TYPE, FIELD_ATTR_LOCAL_TIME } from "../../persistence/db/db-constants.js";
|
|
30
|
+
import { MetaObject } from "../object/meta-object.js";
|
|
31
|
+
import { MetaField } from "../field/meta-field.js";
|
|
32
|
+
import { FIELD_ATTR_CURRENCY, FIELD_ATTR_FILTERABLE, FIELD_ATTR_INT_VALUE_MAP, FIELD_ATTR_MAX_LENGTH, FIELD_ATTR_PRECISION, FIELD_ATTR_REQUIRED, FIELD_ATTR_SCALE, FIELD_ATTR_STORAGE, FIELD_ATTR_VALUES, FIELD_SUBTYPE_MAP, } from "../field/field-constants.js";
|
|
33
|
+
import { opsForField } from "../query/query-constants.js";
|
|
34
|
+
import { reportShape } from "./report-shape.js";
|
|
35
|
+
/**
|
|
36
|
+
* Table B: the type-shaping attrs a derived field carries from its `typeSource`,
|
|
37
|
+
* read with the RESOLVING accessor (ADR-0039) so a value the `@of` field inherits
|
|
38
|
+
* through `extends` is carried too. `@dbColumnType` and `isArray` are handled
|
|
39
|
+
* separately below. Nothing else is carried: no `@column`, `@required`,
|
|
40
|
+
* `@default`, validators or views.
|
|
41
|
+
*/
|
|
42
|
+
const CARRIED_ATTRS = [
|
|
43
|
+
FIELD_ATTR_CURRENCY,
|
|
44
|
+
FIELD_ATTR_VALUES,
|
|
45
|
+
FIELD_ATTR_INT_VALUE_MAP,
|
|
46
|
+
FIELD_ATTR_MAX_LENGTH,
|
|
47
|
+
FIELD_ATTR_PRECISION,
|
|
48
|
+
FIELD_ATTR_SCALE,
|
|
49
|
+
FIELD_ATTR_LOCAL_TIME,
|
|
50
|
+
FIELD_ATTR_STORAGE,
|
|
51
|
+
];
|
|
52
|
+
/** True for a derived field whose source field is an array or a `field.map`. */
|
|
53
|
+
function isArrayOrMap(field) {
|
|
54
|
+
return field.resolvedIsArray() || field.subType === FIELD_SUBTYPE_MAP;
|
|
55
|
+
}
|
|
56
|
+
function derivedField(f) {
|
|
57
|
+
const field = new MetaField(new TypeId(TYPE_FIELD, f.subType), f.name);
|
|
58
|
+
// From the derived shape, never from the type source: a `min` of a required column
|
|
59
|
+
// is still nullable, and a dimension reached by `@via` is nullable.
|
|
60
|
+
field.setAttr(FIELD_ATTR_REQUIRED, f.required);
|
|
61
|
+
const src = f.typeSource;
|
|
62
|
+
if (src !== undefined) {
|
|
63
|
+
for (const name of CARRIED_ATTRS) {
|
|
64
|
+
const value = src.attr(name);
|
|
65
|
+
if (value !== undefined)
|
|
66
|
+
field.setAttr(name, value);
|
|
67
|
+
}
|
|
68
|
+
// ADR-0039: own — `@dbColumnType` is the one deliberately own-only attr (a
|
|
69
|
+
// physical column-type override is never inherited), and every consumer reads
|
|
70
|
+
// it with `ownAttr`. So it is read own from the type source and set OWN here:
|
|
71
|
+
// the derived field carries exactly what the `@of` field itself declares, and
|
|
72
|
+
// nothing its supers declare. A field that `extends` another does not get the
|
|
73
|
+
// parent's `@dbColumnType` either, so this matches how a projection field
|
|
74
|
+
// would see it.
|
|
75
|
+
const dbColumnType = src.ownAttr(FIELD_ATTR_DB_COLUMN_TYPE);
|
|
76
|
+
if (dbColumnType !== undefined)
|
|
77
|
+
field.setAttr(FIELD_ATTR_DB_COLUMN_TYPE, dbColumnType);
|
|
78
|
+
// `isArray` is a native flag, not an attr; resolvedIsArray() is its resolving read.
|
|
79
|
+
if (src.resolvedIsArray())
|
|
80
|
+
field.setIsArray(true);
|
|
81
|
+
}
|
|
82
|
+
// Table C (Plan 3): a report author has no node to put @filterable on, so every
|
|
83
|
+
// derived field that has a filter band is filterable, and (the sort allowlist follows
|
|
84
|
+
// `@filterable`) sortable. Set on this detached model only; no vocabulary is added and the
|
|
85
|
+
// declared tree is not touched. EXCEPT an array or a map: an array column cannot be compared
|
|
86
|
+
// with a scalar (`text[] = text` is a Postgres error), and the entity rule already refuses
|
|
87
|
+
// `@filterable` on an array field, so a derived field whose source is either is neither
|
|
88
|
+
// filterable nor sortable, in every port.
|
|
89
|
+
if (!isArrayOrMap(field) && opsForField(field).length > 0)
|
|
90
|
+
field.setAttr(FIELD_ATTR_FILTERABLE, true);
|
|
91
|
+
return field;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The source a report is READ from: its own read-only source with `@role: primary`,
|
|
95
|
+
* else its first own read-only source. Undefined when it declares none (Table A:
|
|
96
|
+
* not lowered, not served).
|
|
97
|
+
*
|
|
98
|
+
* This is the rule that NAMES the lowered view — `viewName` / `projectionViewSource`
|
|
99
|
+
* in codegen-ts's `projection/extract-view-spec.ts`, reached for a report through
|
|
100
|
+
* `projectionViewName`. It is restated here because the metadata package cannot
|
|
101
|
+
* depend on a codegen package; the two must stay the same rule, or the runtime
|
|
102
|
+
* reads a relation the lowering did not create.
|
|
103
|
+
*
|
|
104
|
+
* What the loader permits, measured: a report may declare several read-only sources
|
|
105
|
+
* (a `@role: replica` view beside its primary view loads clean, in either order);
|
|
106
|
+
* `@role` defaults to `primary`; a report whose sources include no primary is
|
|
107
|
+
* `ERR_SOURCE_NO_PRIMARY` and a writable source on a report is refused. So for every
|
|
108
|
+
* model that loads, the primary branch fires. The first-read-only fallback covers a
|
|
109
|
+
* tree built in code, and keeps this rule identical to the lowering's.
|
|
110
|
+
*/
|
|
111
|
+
export function reportReadSource(report) {
|
|
112
|
+
// ADR-0039: own — source classification reads the sources the report declares
|
|
113
|
+
// ITSELF, exactly as the lowering's `viewName` does.
|
|
114
|
+
const readOnly = report.ownChildren().filter(isReadOnlySource);
|
|
115
|
+
return readOnly.find((s) => s.role === SOURCE_ROLE_PRIMARY) ?? readOnly[0];
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* A detached copy of a source node: same `type.subType`, name and effective attrs,
|
|
119
|
+
* and nothing else (attrs only — the loaded node is never re-parented).
|
|
120
|
+
*
|
|
121
|
+
* The copy is the model's ONLY source, and it is pinned to `@role: primary`: the
|
|
122
|
+
* runtime resolves an object's table through `primaryRdbSource`, which considers
|
|
123
|
+
* primary sources only, so this is what makes the read land on the selected
|
|
124
|
+
* source's physical name rather than on a default table name nobody declared.
|
|
125
|
+
*/
|
|
126
|
+
function copySource(source) {
|
|
127
|
+
const copy = new MetaSource(source.typeId, source.name);
|
|
128
|
+
// ADR-0039: resolving — the copy carries the source's effective configuration
|
|
129
|
+
// (@kind, the physical-name alias, @schema, @unmanaged, @sql).
|
|
130
|
+
for (const [name, value] of source.attrs())
|
|
131
|
+
copy.setAttr(name, value);
|
|
132
|
+
copy.setAttr(SOURCE_ATTR_ROLE, SOURCE_ROLE_PRIMARY);
|
|
133
|
+
return copy;
|
|
134
|
+
}
|
|
135
|
+
const READ_MODELS = new WeakMap();
|
|
136
|
+
/**
|
|
137
|
+
* The read model of an `object.report`: one field per Table B row, in Table B
|
|
138
|
+
* order, plus a copy of the source the report is read from (see
|
|
139
|
+
* `reportReadSource`) when it declares one (Table A). A sourceless report yields a model with no source: it has a shape
|
|
140
|
+
* and no view, and the caller decides what that means (the runtime refuses to
|
|
141
|
+
* serve it).
|
|
142
|
+
*
|
|
143
|
+
* Cached per report node; the model is frozen. Throws what `reportShape` throws
|
|
144
|
+
* when a reference does not resolve.
|
|
145
|
+
*/
|
|
146
|
+
export function reportReadModel(report, root) {
|
|
147
|
+
const cached = READ_MODELS.get(report);
|
|
148
|
+
if (cached !== undefined)
|
|
149
|
+
return cached;
|
|
150
|
+
const shape = reportShape(report, root);
|
|
151
|
+
const model = new MetaObject(report.typeId, report.name);
|
|
152
|
+
if (report.package !== undefined)
|
|
153
|
+
model.setPackage(report.package);
|
|
154
|
+
if (report.fileDefaultPackage !== undefined)
|
|
155
|
+
model.setFileDefaultPackage(report.fileDefaultPackage);
|
|
156
|
+
for (const f of shape.fields)
|
|
157
|
+
model.addChild(derivedField(f));
|
|
158
|
+
const source = reportReadSource(report);
|
|
159
|
+
if (source !== undefined)
|
|
160
|
+
model.addChild(copySource(source));
|
|
161
|
+
model.freeze();
|
|
162
|
+
READ_MODELS.set(report, model);
|
|
163
|
+
return model;
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=report-read-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-read-model.js","sourceRoot":"","sources":["../../../src/core/reporting/report-read-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { MetaData } from "../../shared/meta-data.js";
|
|
2
|
+
import type { MetaRoot } from "../../shared/meta-root.js";
|
|
3
|
+
import type { MetaObject } from "../object/meta-object.js";
|
|
4
|
+
import type { MetaField } from "../field/meta-field.js";
|
|
5
|
+
import { MetaDimension } from "./meta-dimension.js";
|
|
6
|
+
import { MetaMeasure } from "./meta-measure.js";
|
|
7
|
+
import { type TimeGrain } from "./reporting-constants.js";
|
|
8
|
+
export type ReportFieldRole = "dimension" | "measure";
|
|
9
|
+
export interface ReportField {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly role: ReportFieldRole;
|
|
12
|
+
/** A field subtype name (FIELD_SUBTYPE_*). */
|
|
13
|
+
readonly subType: string;
|
|
14
|
+
readonly required: boolean;
|
|
15
|
+
/** The `@of` field whose type-shaping attrs this field carries (Table B). */
|
|
16
|
+
readonly typeSource?: MetaField;
|
|
17
|
+
readonly dimension?: MetaDimension;
|
|
18
|
+
readonly grain?: TimeGrain;
|
|
19
|
+
readonly measure?: MetaMeasure;
|
|
20
|
+
}
|
|
21
|
+
export interface ReportShape {
|
|
22
|
+
readonly report: MetaObject;
|
|
23
|
+
readonly from: MetaObject;
|
|
24
|
+
readonly fields: readonly ReportField[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The entity that DECLARES a dimension, measure or segment reached through `from`: the
|
|
28
|
+
* member's parent, which is `from` itself or an entity `from` extends. A bare entity name
|
|
29
|
+
* inside the member (`@of`, `@via`) resolves in THIS entity's package, exactly as the
|
|
30
|
+
* loader's `validateReporting` resolves it (`pkgOf(ctx.declaring)`), never in `from`'s
|
|
31
|
+
* package or the report's.
|
|
32
|
+
*/
|
|
33
|
+
export declare function reportingMemberOwner(member: MetaData, from: MetaObject): MetaData;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a dimension's or measure's `Entity.field` reference to the field node. The ONE
|
|
36
|
+
* rule, the same as the loader's (`validateReporting` D1 / M1):
|
|
37
|
+
*
|
|
38
|
+
* 1. The entity half resolves relative to the package of `declaring`, the entity that
|
|
39
|
+
* declares the member ({@link reportingMemberOwner}).
|
|
40
|
+
* 2. With `host` (a measure, or a dimension without `@via`: the reference is about the
|
|
41
|
+
* `@from` entity's own rows) the named entity must be `host` or an entity it extends,
|
|
42
|
+
* and the field is read from `host`, so a field `host` redeclares wins.
|
|
43
|
+
* 3. Without `host` the field is read from the named entity. A dimension with `@via` passes
|
|
44
|
+
* the entity its `@via` reaches as both `declaring` and `host`
|
|
45
|
+
* ({@link resolveDimensionOf}).
|
|
46
|
+
*
|
|
47
|
+
* Undefined when any step fails.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveReportingFieldRef(ref: string, declaring: MetaData, root: MetaRoot, host?: MetaObject): MetaField | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* A dimension's `@of` field, read as the loader's rule D1 reads it. Without `@via` it is
|
|
52
|
+
* {@link resolveReportingFieldRef} with `from` as the host. With `@via` the host is the
|
|
53
|
+
* entity the `@via` reaches, and a bare entity name in `@of` resolves in THAT entity's
|
|
54
|
+
* package: the path already fixes the entity, so `Realm.name` after a hop onto
|
|
55
|
+
* `world::Realm` names `world::Realm`. The field is read from the reached entity, so a field
|
|
56
|
+
* it redeclares wins. Undefined when the `@via` or the `@of` does not resolve.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveDimensionOf(dim: MetaDimension, from: MetaObject, root: MetaRoot): {
|
|
59
|
+
readonly named: MetaObject;
|
|
60
|
+
readonly field: MetaField;
|
|
61
|
+
} | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* The hop names of a dimension's `@via` (`Owner.hop[.hop...]`), read as the loader reads it
|
|
64
|
+
* (`validateReporting` rule D2): `Owner` resolves in the package of `declaring`
|
|
65
|
+
* ({@link reportingMemberOwner}) and must be `from` or an entity `from` extends. The walk
|
|
66
|
+
* itself then starts AT `from`, whichever of the two `Owner` named. Undefined when the
|
|
67
|
+
* reference has no owner, no hop, or an owner that is not `from` or an ancestor of it.
|
|
68
|
+
*/
|
|
69
|
+
export declare function reportingViaHops(via: string, declaring: MetaData, from: MetaObject, root: MetaRoot): string[] | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* The hop names of a report's `@spine` (`Owner.hop[.hop...]`), read as
|
|
72
|
+
* {@link reportingViaHops} reads a `@via`, the owner resolving in `from`'s package (loader
|
|
73
|
+
* rule R8): Owner must be `from` or an entity it extends, so a bare name means `from`'s
|
|
74
|
+
* package even when the report lives in another one. Undefined when the report declares no `@spine`. Throws a plain Error
|
|
75
|
+
* naming the report when a declared `@spine` does not resolve (a report that passed
|
|
76
|
+
* `validateReporting` always resolves): reading it as "no spine" would claim a column
|
|
77
|
+
* non-null that a spine row with no facts leaves null.
|
|
78
|
+
*/
|
|
79
|
+
export declare function reportSpineHops(report: MetaObject, from: MetaObject, root: MetaRoot): string[] | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* The spine entity: the object at the end of a report's `@spine`, whose rows are the
|
|
82
|
+
* report's rows. Walked hop by hop from `from` as the loader's rule R8 walks it via
|
|
83
|
+
* {@link resolveViaHop}; an unresolved hop throws, as {@link reportSpineHops} does (a report
|
|
84
|
+
* that passed `validateReporting` always resolves). Undefined when the report declares no
|
|
85
|
+
* `@spine`.
|
|
86
|
+
*/
|
|
87
|
+
export declare function reportSpineEntity(report: MetaObject, from: MetaObject, root: MetaRoot): MetaObject | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Table B's subtype for one measure of `from`, whether or not a report lists it (a
|
|
90
|
+
* ratio's operands are measures a report need not list). The same rule `reportShape`
|
|
91
|
+
* applies to a listed measure. Undefined when its `@of` does not resolve, which the
|
|
92
|
+
* loader (rule M6) reads before the model is known to be valid.
|
|
93
|
+
*/
|
|
94
|
+
export declare function measureResultSubType(measure: MetaMeasure, from: MetaObject, root: MetaRoot): string | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* {@link measureResultSubType} for a model that passed `validateReporting`. Throws a plain
|
|
97
|
+
* Error naming the measure when its `@of` does not resolve (a valid measure always resolves).
|
|
98
|
+
*/
|
|
99
|
+
export declare function measureDerivedSubType(measure: MetaMeasure, from: MetaObject, root: MetaRoot): string;
|
|
100
|
+
/** Table B, with Table C's `required`. Throws a plain Error naming the report when a
|
|
101
|
+
* reference does not resolve (a report that passed `validateReporting` always resolves). */
|
|
102
|
+
export declare function reportShape(report: MetaObject, root: MetaRoot): ReportShape;
|
|
103
|
+
//# sourceMappingURL=report-shape.d.ts.map
|