@metaobjectsdev/metadata 0.5.0-rc.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 +189 -0
- package/README.md +29 -0
- package/dist/attr-class-map.d.ts +26 -0
- package/dist/attr-class-map.d.ts.map +1 -0
- package/dist/attr-class-map.js +44 -0
- package/dist/attr-class-map.js.map +1 -0
- package/dist/attr-schema-validate.d.ts +9 -0
- package/dist/attr-schema-validate.d.ts.map +1 -0
- package/dist/attr-schema-validate.js +100 -0
- package/dist/attr-schema-validate.js.map +1 -0
- package/dist/constants.d.ts +208 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +419 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/attr/attr-constants.d.ts +12 -0
- package/dist/core/attr/attr-constants.d.ts.map +1 -0
- package/dist/core/attr/attr-constants.js +27 -0
- package/dist/core/attr/attr-constants.js.map +1 -0
- package/dist/core/attr/meta-attr-filter.d.ts +10 -0
- package/dist/core/attr/meta-attr-filter.d.ts.map +1 -0
- package/dist/core/attr/meta-attr-filter.js +56 -0
- package/dist/core/attr/meta-attr-filter.js.map +1 -0
- package/dist/core/attr/meta-attr-properties.d.ts +9 -0
- package/dist/core/attr/meta-attr-properties.d.ts.map +1 -0
- package/dist/core/attr/meta-attr-properties.js +22 -0
- package/dist/core/attr/meta-attr-properties.js.map +1 -0
- package/dist/core/attr/meta-attr-stringarray.d.ts +9 -0
- package/dist/core/attr/meta-attr-stringarray.d.ts.map +1 -0
- package/dist/core/attr/meta-attr-stringarray.js +29 -0
- package/dist/core/attr/meta-attr-stringarray.js.map +1 -0
- package/dist/core/attr/meta-attr.d.ts +37 -0
- package/dist/core/attr/meta-attr.d.ts.map +1 -0
- package/dist/core/attr/meta-attr.js +97 -0
- package/dist/core/attr/meta-attr.js.map +1 -0
- package/dist/core/export-json.d.ts +29 -0
- package/dist/core/export-json.d.ts.map +1 -0
- package/dist/core/export-json.js +45 -0
- package/dist/core/export-json.js.map +1 -0
- package/dist/core/field/field-constants.d.ts +40 -0
- package/dist/core/field/field-constants.d.ts.map +1 -0
- package/dist/core/field/field-constants.js +66 -0
- package/dist/core/field/field-constants.js.map +1 -0
- package/dist/core/field/field-schema.d.ts +6 -0
- package/dist/core/field/field-schema.d.ts.map +1 -0
- package/dist/core/field/field-schema.js +92 -0
- package/dist/core/field/field-schema.js.map +1 -0
- package/dist/core/field/meta-field.d.ts +50 -0
- package/dist/core/field/meta-field.d.ts.map +1 -0
- package/dist/core/field/meta-field.js +121 -0
- package/dist/core/field/meta-field.js.map +1 -0
- package/dist/core/file-meta-data-loader.d.ts +18 -0
- package/dist/core/file-meta-data-loader.d.ts.map +1 -0
- package/dist/core/file-meta-data-loader.js +81 -0
- package/dist/core/file-meta-data-loader.js.map +1 -0
- package/dist/core/file-source.d.ts +12 -0
- package/dist/core/file-source.d.ts.map +1 -0
- package/dist/core/file-source.js +46 -0
- package/dist/core/file-source.js.map +1 -0
- package/dist/core/identity/identity-constants.d.ts +19 -0
- package/dist/core/identity/identity-constants.d.ts.map +1 -0
- package/dist/core/identity/identity-constants.js +35 -0
- package/dist/core/identity/identity-constants.js.map +1 -0
- package/dist/core/identity/identity-schema.d.ts +6 -0
- package/dist/core/identity/identity-schema.d.ts.map +1 -0
- package/dist/core/identity/identity-schema.js +55 -0
- package/dist/core/identity/identity-schema.js.map +1 -0
- package/dist/core/identity/meta-identity.d.ts +71 -0
- package/dist/core/identity/meta-identity.d.ts.map +1 -0
- package/dist/core/identity/meta-identity.js +129 -0
- package/dist/core/identity/meta-identity.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +11 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/object/meta-object.d.ts +39 -0
- package/dist/core/object/meta-object.d.ts.map +1 -0
- package/dist/core/object/meta-object.js +80 -0
- package/dist/core/object/meta-object.js.map +1 -0
- package/dist/core/object/object-constants.d.ts +5 -0
- package/dist/core/object/object-constants.d.ts.map +1 -0
- package/dist/core/object/object-constants.js +18 -0
- package/dist/core/object/object-constants.js.map +1 -0
- package/dist/core/object/object-schema.d.ts +4 -0
- package/dist/core/object/object-schema.d.ts.map +1 -0
- package/dist/core/object/object-schema.js +5 -0
- package/dist/core/object/object-schema.js.map +1 -0
- package/dist/core/parser-yaml.d.ts +3 -0
- package/dist/core/parser-yaml.d.ts.map +1 -0
- package/dist/core/parser-yaml.js +39 -0
- package/dist/core/parser-yaml.js.map +1 -0
- package/dist/core/query/query-constants.d.ts +20 -0
- package/dist/core/query/query-constants.d.ts.map +1 -0
- package/dist/core/query/query-constants.js +56 -0
- package/dist/core/query/query-constants.js.map +1 -0
- package/dist/core/relationship/find-reference.d.ts +22 -0
- package/dist/core/relationship/find-reference.d.ts.map +1 -0
- package/dist/core/relationship/find-reference.js +29 -0
- package/dist/core/relationship/find-reference.js.map +1 -0
- package/dist/core/relationship/meta-relationship.d.ts +11 -0
- package/dist/core/relationship/meta-relationship.d.ts.map +1 -0
- package/dist/core/relationship/meta-relationship.js +27 -0
- package/dist/core/relationship/meta-relationship.js.map +1 -0
- package/dist/core/relationship/relationship-constants.d.ts +14 -0
- package/dist/core/relationship/relationship-constants.d.ts.map +1 -0
- package/dist/core/relationship/relationship-constants.js +28 -0
- package/dist/core/relationship/relationship-constants.js.map +1 -0
- package/dist/core/relationship/relationship-schema.d.ts +4 -0
- package/dist/core/relationship/relationship-schema.d.ts.map +1 -0
- package/dist/core/relationship/relationship-schema.js +37 -0
- package/dist/core/relationship/relationship-schema.js.map +1 -0
- package/dist/core/validator/meta-validator.d.ts +29 -0
- package/dist/core/validator/meta-validator.d.ts.map +1 -0
- package/dist/core/validator/meta-validator.js +49 -0
- package/dist/core/validator/meta-validator.js.map +1 -0
- package/dist/core/validator/validator-constants.d.ts +11 -0
- package/dist/core/validator/validator-constants.d.ts.map +1 -0
- package/dist/core/validator/validator-constants.js +25 -0
- package/dist/core/validator/validator-constants.js.map +1 -0
- package/dist/core/validator/validator-schema.d.ts +4 -0
- package/dist/core/validator/validator-schema.d.ts.map +1 -0
- package/dist/core/validator/validator-schema.js +38 -0
- package/dist/core/validator/validator-schema.js.map +1 -0
- package/dist/core/yaml-desugar.d.ts +10 -0
- package/dist/core/yaml-desugar.d.ts.map +1 -0
- package/dist/core/yaml-desugar.js +99 -0
- package/dist/core/yaml-desugar.js.map +1 -0
- package/dist/core-attr-schemas.d.ts +22 -0
- package/dist/core-attr-schemas.d.ts.map +1 -0
- package/dist/core-attr-schemas.js +324 -0
- package/dist/core-attr-schemas.js.map +1 -0
- package/dist/core-types.d.ts +20 -0
- package/dist/core-types.d.ts.map +1 -0
- package/dist/core-types.js +225 -0
- package/dist/core-types.js.map +1 -0
- package/dist/data-converter.d.ts +17 -0
- package/dist/data-converter.d.ts.map +1 -0
- package/dist/data-converter.js +117 -0
- package/dist/data-converter.js.map +1 -0
- package/dist/data-type.d.ts +15 -0
- package/dist/data-type.d.ts.map +1 -0
- package/dist/data-type.js +25 -0
- package/dist/data-type.js.map +1 -0
- package/dist/db/db-attr-schemas.d.ts +8 -0
- package/dist/db/db-attr-schemas.d.ts.map +1 -0
- package/dist/db/db-attr-schemas.js +26 -0
- package/dist/db/db-attr-schemas.js.map +1 -0
- package/dist/db/db-provider.d.ts +3 -0
- package/dist/db/db-provider.d.ts.map +1 -0
- package/dist/db/db-provider.js +28 -0
- package/dist/db/db-provider.js.map +1 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/loader/meta-data-loader.d.ts +87 -0
- package/dist/loader/meta-data-loader.d.ts.map +1 -0
- package/dist/loader/meta-data-loader.js +232 -0
- package/dist/loader/meta-data-loader.js.map +1 -0
- package/dist/loader/meta-data-source.d.ts +23 -0
- package/dist/loader/meta-data-source.d.ts.map +1 -0
- package/dist/loader/meta-data-source.js +20 -0
- package/dist/loader/meta-data-source.js.map +1 -0
- package/dist/loader/validation-passes.d.ts +7 -0
- package/dist/loader/validation-passes.d.ts.map +1 -0
- package/dist/loader/validation-passes.js +244 -0
- package/dist/loader/validation-passes.js.map +1 -0
- package/dist/meta/find-reference.d.ts +22 -0
- package/dist/meta/find-reference.d.ts.map +1 -0
- package/dist/meta/find-reference.js +29 -0
- package/dist/meta/find-reference.js.map +1 -0
- package/dist/meta/meta-attr.d.ts +8 -0
- package/dist/meta/meta-attr.d.ts.map +1 -0
- package/dist/meta/meta-attr.js +17 -0
- package/dist/meta/meta-attr.js.map +1 -0
- package/dist/meta/meta-data.d.ts +107 -0
- package/dist/meta/meta-data.d.ts.map +1 -0
- package/dist/meta/meta-data.js +302 -0
- package/dist/meta/meta-data.js.map +1 -0
- package/dist/meta/meta-field.d.ts +48 -0
- package/dist/meta/meta-field.d.ts.map +1 -0
- package/dist/meta/meta-field.js +94 -0
- package/dist/meta/meta-field.js.map +1 -0
- package/dist/meta/meta-identity.d.ts +71 -0
- package/dist/meta/meta-identity.d.ts.map +1 -0
- package/dist/meta/meta-identity.js +129 -0
- package/dist/meta/meta-identity.js.map +1 -0
- package/dist/meta/meta-layout.d.ts +23 -0
- package/dist/meta/meta-layout.d.ts.map +1 -0
- package/dist/meta/meta-layout.js +45 -0
- package/dist/meta/meta-layout.js.map +1 -0
- package/dist/meta/meta-object.d.ts +40 -0
- package/dist/meta/meta-object.d.ts.map +1 -0
- package/dist/meta/meta-object.js +81 -0
- package/dist/meta/meta-object.js.map +1 -0
- package/dist/meta/meta-origin.d.ts +32 -0
- package/dist/meta/meta-origin.d.ts.map +1 -0
- package/dist/meta/meta-origin.js +55 -0
- package/dist/meta/meta-origin.js.map +1 -0
- package/dist/meta/meta-relationship.d.ts +11 -0
- package/dist/meta/meta-relationship.d.ts.map +1 -0
- package/dist/meta/meta-relationship.js +27 -0
- package/dist/meta/meta-relationship.js.map +1 -0
- package/dist/meta/meta-root.d.ts +12 -0
- package/dist/meta/meta-root.d.ts.map +1 -0
- package/dist/meta/meta-root.js +24 -0
- package/dist/meta/meta-root.js.map +1 -0
- package/dist/meta/meta-source.d.ts +18 -0
- package/dist/meta/meta-source.d.ts.map +1 -0
- package/dist/meta/meta-source.js +31 -0
- package/dist/meta/meta-source.js.map +1 -0
- package/dist/meta/meta-validator.d.ts +29 -0
- package/dist/meta/meta-validator.d.ts.map +1 -0
- package/dist/meta/meta-validator.js +49 -0
- package/dist/meta/meta-validator.js.map +1 -0
- package/dist/meta/meta-view.d.ts +4 -0
- package/dist/meta/meta-view.d.ts.map +1 -0
- package/dist/meta/meta-view.js +8 -0
- package/dist/meta/meta-view.js.map +1 -0
- package/dist/naming.d.ts +27 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/naming.js +72 -0
- package/dist/naming.js.map +1 -0
- package/dist/object-serializer.d.ts +10 -0
- package/dist/object-serializer.d.ts.map +1 -0
- package/dist/object-serializer.js +128 -0
- package/dist/object-serializer.js.map +1 -0
- package/dist/overlay.d.ts +2 -0
- package/dist/overlay.d.ts.map +1 -0
- package/dist/overlay.js +6 -0
- package/dist/overlay.js.map +1 -0
- package/dist/parser-core.d.ts +47 -0
- package/dist/parser-core.d.ts.map +1 -0
- package/dist/parser-core.js +516 -0
- package/dist/parser-core.js.map +1 -0
- package/dist/parser-json.d.ts +4 -0
- package/dist/parser-json.d.ts.map +1 -0
- package/dist/parser-json.js +19 -0
- package/dist/parser-json.js.map +1 -0
- package/dist/persistence/db/db-attr-schemas.d.ts +8 -0
- package/dist/persistence/db/db-attr-schemas.d.ts.map +1 -0
- package/dist/persistence/db/db-attr-schemas.js +28 -0
- package/dist/persistence/db/db-attr-schemas.js.map +1 -0
- package/dist/persistence/db/db-constants.d.ts +5 -0
- package/dist/persistence/db/db-constants.d.ts.map +1 -0
- package/dist/persistence/db/db-constants.js +6 -0
- package/dist/persistence/db/db-constants.js.map +1 -0
- package/dist/persistence/db/db-provider.d.ts +3 -0
- package/dist/persistence/db/db-provider.d.ts.map +1 -0
- package/dist/persistence/db/db-provider.js +29 -0
- package/dist/persistence/db/db-provider.js.map +1 -0
- package/dist/persistence/db/db-schema.d.ts +8 -0
- package/dist/persistence/db/db-schema.d.ts.map +1 -0
- package/dist/persistence/db/db-schema.js +27 -0
- package/dist/persistence/db/db-schema.js.map +1 -0
- package/dist/persistence/origin/meta-origin.d.ts +32 -0
- package/dist/persistence/origin/meta-origin.d.ts.map +1 -0
- package/dist/persistence/origin/meta-origin.js +55 -0
- package/dist/persistence/origin/meta-origin.js.map +1 -0
- package/dist/persistence/origin/origin-constants.d.ts +12 -0
- package/dist/persistence/origin/origin-constants.d.ts.map +1 -0
- package/dist/persistence/origin/origin-constants.js +27 -0
- package/dist/persistence/origin/origin-constants.js.map +1 -0
- package/dist/persistence/origin/origin-schema.d.ts +4 -0
- package/dist/persistence/origin/origin-schema.d.ts.map +1 -0
- package/dist/persistence/origin/origin-schema.js +49 -0
- package/dist/persistence/origin/origin-schema.js.map +1 -0
- package/dist/persistence/source/meta-source.d.ts +18 -0
- package/dist/persistence/source/meta-source.d.ts.map +1 -0
- package/dist/persistence/source/meta-source.js +31 -0
- package/dist/persistence/source/meta-source.js.map +1 -0
- package/dist/persistence/source/source-constants.d.ts +16 -0
- package/dist/persistence/source/source-constants.d.ts.map +1 -0
- package/dist/persistence/source/source-constants.js +28 -0
- package/dist/persistence/source/source-constants.js.map +1 -0
- package/dist/presentation/layout/layout-constants.d.ts +10 -0
- package/dist/presentation/layout/layout-constants.d.ts.map +1 -0
- package/dist/presentation/layout/layout-constants.js +21 -0
- package/dist/presentation/layout/layout-constants.js.map +1 -0
- package/dist/presentation/layout/layout-schema.d.ts +4 -0
- package/dist/presentation/layout/layout-schema.d.ts.map +1 -0
- package/dist/presentation/layout/layout-schema.js +46 -0
- package/dist/presentation/layout/layout-schema.js.map +1 -0
- package/dist/presentation/layout/meta-layout.d.ts +23 -0
- package/dist/presentation/layout/meta-layout.d.ts.map +1 -0
- package/dist/presentation/layout/meta-layout.js +47 -0
- package/dist/presentation/layout/meta-layout.js.map +1 -0
- package/dist/presentation/view/meta-view.d.ts +4 -0
- package/dist/presentation/view/meta-view.d.ts.map +1 -0
- package/dist/presentation/view/meta-view.js +8 -0
- package/dist/presentation/view/meta-view.js.map +1 -0
- package/dist/presentation/view/view-constants.d.ts +20 -0
- package/dist/presentation/view/view-constants.d.ts.map +1 -0
- package/dist/presentation/view/view-constants.js +47 -0
- package/dist/presentation/view/view-constants.js.map +1 -0
- package/dist/presentation/view/view-schema.d.ts +4 -0
- package/dist/presentation/view/view-schema.d.ts.map +1 -0
- package/dist/presentation/view/view-schema.js +15 -0
- package/dist/presentation/view/view-schema.js.map +1 -0
- package/dist/provider.d.ts +20 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +58 -0
- package/dist/provider.js.map +1 -0
- package/dist/registry.d.ts +89 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +107 -0
- package/dist/registry.js.map +1 -0
- package/dist/serializer-json.d.ts +16 -0
- package/dist/serializer-json.d.ts.map +1 -0
- package/dist/serializer-json.js +154 -0
- package/dist/serializer-json.js.map +1 -0
- package/dist/shared/base-types.d.ts +23 -0
- package/dist/shared/base-types.d.ts.map +1 -0
- package/dist/shared/base-types.js +43 -0
- package/dist/shared/base-types.js.map +1 -0
- package/dist/shared/meta-data.d.ts +123 -0
- package/dist/shared/meta-data.d.ts.map +1 -0
- package/dist/shared/meta-data.js +365 -0
- package/dist/shared/meta-data.js.map +1 -0
- package/dist/shared/meta-root.d.ts +12 -0
- package/dist/shared/meta-root.d.ts.map +1 -0
- package/dist/shared/meta-root.js +24 -0
- package/dist/shared/meta-root.js.map +1 -0
- package/dist/shared/structural.d.ts +20 -0
- package/dist/shared/structural.d.ts.map +1 -0
- package/dist/shared/structural.js +49 -0
- package/dist/shared/structural.js.map +1 -0
- package/dist/subtype-rules.d.ts +8 -0
- package/dist/subtype-rules.d.ts.map +1 -0
- package/dist/subtype-rules.js +34 -0
- package/dist/subtype-rules.js.map +1 -0
- package/dist/super-resolve.d.ts +34 -0
- package/dist/super-resolve.d.ts.map +1 -0
- package/dist/super-resolve.js +124 -0
- package/dist/super-resolve.js.map +1 -0
- package/package.json +50 -0
- package/src/attr-class-map.ts +64 -0
- package/src/attr-schema-validate.ts +134 -0
- package/src/core/attr/attr-constants.ts +31 -0
- package/src/core/attr/meta-attr-filter.ts +67 -0
- package/src/core/attr/meta-attr-properties.ts +26 -0
- package/src/core/attr/meta-attr-stringarray.ts +31 -0
- package/src/core/attr/meta-attr.ts +125 -0
- package/src/core/export-json.ts +66 -0
- package/src/core/field/field-constants.ts +79 -0
- package/src/core/field/field-schema.ts +121 -0
- package/src/core/field/meta-field.ts +179 -0
- package/src/core/file-meta-data-loader.ts +89 -0
- package/src/core/file-source.ts +52 -0
- package/src/core/identity/identity-constants.ts +44 -0
- package/src/core/identity/identity-schema.ts +80 -0
- package/src/core/identity/meta-identity.ts +148 -0
- package/src/core/index.ts +12 -0
- package/src/core/object/meta-object.ts +151 -0
- package/src/core/object/object-constants.ts +21 -0
- package/src/core/object/object-schema.ts +7 -0
- package/src/core/parser-yaml.ts +54 -0
- package/src/core/query/query-constants.ts +66 -0
- package/src/core/relationship/find-reference.ts +44 -0
- package/src/core/relationship/meta-relationship.ts +36 -0
- package/src/core/relationship/relationship-constants.ts +38 -0
- package/src/core/relationship/relationship-schema.ts +49 -0
- package/src/core/validator/meta-validator.ts +62 -0
- package/src/core/validator/validator-constants.ts +31 -0
- package/src/core/validator/validator-schema.ts +50 -0
- package/src/core/yaml-desugar.ts +145 -0
- package/src/core-types.ts +329 -0
- package/src/data-converter.ts +125 -0
- package/src/data-type.ts +33 -0
- package/src/errors.ts +68 -0
- package/src/index.ts +165 -0
- package/src/loader/meta-data-loader.ts +307 -0
- package/src/loader/meta-data-source.ts +35 -0
- package/src/loader/validation-passes.ts +370 -0
- package/src/naming.ts +86 -0
- package/src/object-serializer.ts +153 -0
- package/src/overlay.ts +5 -0
- package/src/parser-core.ts +815 -0
- package/src/parser-json.ts +28 -0
- package/src/persistence/db/db-constants.ts +6 -0
- package/src/persistence/db/db-provider.ts +36 -0
- package/src/persistence/db/db-schema.ts +40 -0
- package/src/persistence/origin/meta-origin.ts +67 -0
- package/src/persistence/origin/origin-constants.ts +35 -0
- package/src/persistence/origin/origin-schema.ts +66 -0
- package/src/persistence/source/meta-source.ts +38 -0
- package/src/persistence/source/source-constants.ts +35 -0
- package/src/presentation/layout/layout-constants.ts +27 -0
- package/src/presentation/layout/layout-schema.ts +62 -0
- package/src/presentation/layout/meta-layout.ts +61 -0
- package/src/presentation/view/meta-view.ts +8 -0
- package/src/presentation/view/view-constants.ts +53 -0
- package/src/presentation/view/view-schema.ts +21 -0
- package/src/provider.ts +85 -0
- package/src/registry.ts +190 -0
- package/src/serializer-json.ts +210 -0
- package/src/shared/base-types.ts +52 -0
- package/src/shared/meta-data.ts +443 -0
- package/src/shared/meta-root.ts +33 -0
- package/src/shared/structural.ts +62 -0
- package/src/subtype-rules.ts +56 -0
- package/src/super-resolve.ts +147 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { TypeId } from "../registry.js";
|
|
2
|
+
import { TYPE_ATTR } from "./base-types.js";
|
|
3
|
+
import { PACKAGE_SEPARATOR, RESERVED_KEY_VALUE } from "./structural.js";
|
|
4
|
+
import type { DataType } from "../data-type.js";
|
|
5
|
+
import type { MetaAttr } from "../core/attr/meta-attr.js";
|
|
6
|
+
import { inferAttrSubType } from "../serializer-json.js";
|
|
7
|
+
import { attrClassFor } from "../attr-class-map.js";
|
|
8
|
+
|
|
9
|
+
export type AttrValue = string | number | boolean | string[] | AttrObject;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Object-shaped attr value (for `attr.filter` / `attr.properties`). Values are
|
|
13
|
+
* arbitrary JSON so a filter can hold nested `{ op: value }` clauses (including
|
|
14
|
+
* scalar arrays for `in` and `null` for `isNull`). Scalar/string[] attrs keep
|
|
15
|
+
* their existing arms — this arm is reached only by object-typed attr subtypes.
|
|
16
|
+
*/
|
|
17
|
+
export type AttrObject = { readonly [key: string]: AttrJson };
|
|
18
|
+
export type AttrJson = string | number | boolean | null | AttrJson[] | AttrObject;
|
|
19
|
+
|
|
20
|
+
export abstract class MetaData {
|
|
21
|
+
readonly typeId: TypeId;
|
|
22
|
+
readonly name: string;
|
|
23
|
+
|
|
24
|
+
// Identity / packaging
|
|
25
|
+
package?: string;
|
|
26
|
+
superRef?: string; // raw super reference string, pre-resolution
|
|
27
|
+
private _superData?: MetaData; // post-resolution pointer; set by setSuperResolved() after parsing
|
|
28
|
+
isAbstract: boolean = false;
|
|
29
|
+
|
|
30
|
+
// Native @isArray (boolean property, NOT in attrs!)
|
|
31
|
+
isArray: boolean = false;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Per-node merge flag (v0.3 `merge: true` operator).
|
|
35
|
+
*
|
|
36
|
+
* When `true` on a node being parsed:
|
|
37
|
+
* - If an existing same-(type,name) child is found in the current parent → reuse it (merge into it).
|
|
38
|
+
* - If NOT found → throw: "Merge operation requested for [...] but no existing metadata found".
|
|
39
|
+
*/
|
|
40
|
+
isMerge: boolean = false;
|
|
41
|
+
|
|
42
|
+
// Internal storage — attributes as MetaAttr instances, name-indexed and
|
|
43
|
+
// insertion-ordered. NOT in _children (attrs never appear in ownChildren()).
|
|
44
|
+
private _attrNodes = new Map<string, MetaAttr>();
|
|
45
|
+
// A MetaAttr's own scalar/array/object value is a terminal stored under the
|
|
46
|
+
// reserved "value" key. It is NOT materialized as a nested MetaAttr (that
|
|
47
|
+
// would recurse forever — every node would build a child to hold its value,
|
|
48
|
+
// which would build a child, ...). Read via ownAttr(RESERVED_KEY_VALUE) /
|
|
49
|
+
// MetaAttr.value; set via setAttr(RESERVED_KEY_VALUE, ...).
|
|
50
|
+
private _ownValue?: AttrValue;
|
|
51
|
+
private _ownValueSet = false;
|
|
52
|
+
private _children: MetaData[] = [];
|
|
53
|
+
private _parent?: MetaData;
|
|
54
|
+
private _frozen: boolean = false;
|
|
55
|
+
|
|
56
|
+
// Registry-supplied coarse value type — set by the registry factory at node
|
|
57
|
+
// construction (for field/attr nodes). Read via MetaField/MetaAttr.dataType.
|
|
58
|
+
protected _dataType?: DataType;
|
|
59
|
+
|
|
60
|
+
// Per-instance read cache: only populated once the node is frozen.
|
|
61
|
+
private readonly _cache = new Map<string, unknown>();
|
|
62
|
+
|
|
63
|
+
constructor(typeId: TypeId, name: string) {
|
|
64
|
+
this.typeId = typeId;
|
|
65
|
+
this.name = name;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// Cache helper
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Memoize a derived read. Only caches once the node is frozen — a value
|
|
74
|
+
* computed during the (mutable) load phase is never stored, so it cannot
|
|
75
|
+
* go stale. After freeze the tree is immutable, so a cached entry is valid
|
|
76
|
+
* for the node's lifetime; there is no invalidation.
|
|
77
|
+
*/
|
|
78
|
+
protected cached<T>(key: string, compute: () => T): T {
|
|
79
|
+
if (this._frozen && this._cache.has(key)) {
|
|
80
|
+
return this._cache.get(key) as T;
|
|
81
|
+
}
|
|
82
|
+
const value = compute();
|
|
83
|
+
if (this._frozen) this._cache.set(key, value);
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Convenience accessors
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
get type(): string {
|
|
92
|
+
return this.typeId.type;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get subType(): string {
|
|
96
|
+
return this.typeId.subType;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** "package::name" if package is set, else just "name". Uses :: as separator (not .). */
|
|
100
|
+
fqn(): string {
|
|
101
|
+
if (this.package !== undefined) {
|
|
102
|
+
return `${this.package}${PACKAGE_SEPARATOR}${this.name}`;
|
|
103
|
+
}
|
|
104
|
+
return this.name;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// Freeze guard
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
private _assertNotFrozen(): void {
|
|
112
|
+
if (this._frozen) {
|
|
113
|
+
throw new Error(`Cannot mutate frozen MetaData ${this.fqn()}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Package
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
setPackage(pkg: string): void {
|
|
122
|
+
this._assertNotFrozen();
|
|
123
|
+
this.package = pkg;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Super
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
|
|
130
|
+
/** Returns the resolved super model, or undefined if not yet resolved. */
|
|
131
|
+
get superData(): MetaData | undefined {
|
|
132
|
+
return this._superData;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Temporary compatibility alias for `superData` — kept while super-resolve.ts still references this name; to be removed in a later task. */
|
|
136
|
+
get superResolved(): MetaData | undefined {
|
|
137
|
+
return this._superData;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Sets the resolved super model. Normally called by Task 6's super resolution
|
|
142
|
+
* after parsing and before freezing.
|
|
143
|
+
*/
|
|
144
|
+
setSuperResolved(model: MetaData): void {
|
|
145
|
+
this._assertNotFrozen();
|
|
146
|
+
this._superData = model;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
setSuper(ref: string): void {
|
|
150
|
+
this._assertNotFrozen();
|
|
151
|
+
this.superRef = ref;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
// isArray
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
|
|
158
|
+
setIsArray(val: boolean): void {
|
|
159
|
+
this._assertNotFrozen();
|
|
160
|
+
this.isArray = val;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// dataType
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
/** Set the registry-supplied DataType. Called by the registry factory at
|
|
168
|
+
* node construction. */
|
|
169
|
+
setDataType(dt: DataType): void {
|
|
170
|
+
this._assertNotFrozen();
|
|
171
|
+
this._dataType = dt;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
// isAbstract
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
|
|
178
|
+
setIsAbstract(val: boolean): void {
|
|
179
|
+
this._assertNotFrozen();
|
|
180
|
+
this.isAbstract = val;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
// isMerge
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
|
|
187
|
+
setIsMerge(val: boolean): void {
|
|
188
|
+
this._assertNotFrozen();
|
|
189
|
+
this.isMerge = val;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// Attributes
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
setAttr(name: string, value: AttrValue): void {
|
|
197
|
+
this._assertNotFrozen();
|
|
198
|
+
// The reserved "value" key is a node's own terminal value (e.g. a MetaAttr's
|
|
199
|
+
// value). It is stored directly, never materialized as a nested MetaAttr —
|
|
200
|
+
// doing so would recurse forever (each node would build a child to hold its
|
|
201
|
+
// value). See _ownValue.
|
|
202
|
+
if (name === RESERVED_KEY_VALUE) {
|
|
203
|
+
this._ownValue = value;
|
|
204
|
+
this._ownValueSet = true;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const existing = this._attrNodes.get(name);
|
|
208
|
+
if (existing !== undefined) {
|
|
209
|
+
existing.setAttr(RESERVED_KEY_VALUE, value);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
// Resolve the attr's class. A declared subtype isn't known here (this is the
|
|
213
|
+
// node, not the registry), so infer from the value shape — same rule the
|
|
214
|
+
// serializer uses. The parser, which DOES know the declared subtype, builds
|
|
215
|
+
// the instance directly via setMetaAttr (below).
|
|
216
|
+
const subType = inferAttrSubType(value);
|
|
217
|
+
const AttrClass = attrClassFor(subType);
|
|
218
|
+
const node = new AttrClass(new TypeId(TYPE_ATTR, subType), name);
|
|
219
|
+
node.setAttr(RESERVED_KEY_VALUE, value);
|
|
220
|
+
this._attrNodes.set(name, node);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** Attach a pre-built MetaAttr instance (the parser path, which knows the
|
|
224
|
+
* declared subtype). Replaces any existing attr of the same name. */
|
|
225
|
+
setMetaAttr(node: MetaAttr): void {
|
|
226
|
+
this._assertNotFrozen();
|
|
227
|
+
this._attrNodes.set(node.name, node);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Own (locally declared) attr value for `name`, or undefined — excludes inherited. */
|
|
231
|
+
ownAttr(name: string): AttrValue | undefined {
|
|
232
|
+
if (name === RESERVED_KEY_VALUE) {
|
|
233
|
+
return this._ownValueSet ? this._ownValue : undefined;
|
|
234
|
+
}
|
|
235
|
+
return this._attrNodes.get(name)?.value;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Own (locally declared) MetaAttr instance for `name`, or undefined. */
|
|
239
|
+
ownMetaAttr(name: string): MetaAttr | undefined {
|
|
240
|
+
return this._attrNodes.get(name);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Own MetaAttr instances, insertion-ordered, frozen; excludes inherited. */
|
|
244
|
+
ownMetaAttrs(): readonly MetaAttr[] {
|
|
245
|
+
return this.cached("ownMetaAttrs", () => Object.freeze([...this._attrNodes.values()]));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Own (locally declared) attr value map; excludes inherited. Cached. */
|
|
249
|
+
ownAttrs(): ReadonlyMap<string, AttrValue> {
|
|
250
|
+
return this.cached("ownAttrs", () => {
|
|
251
|
+
const m = new Map<string, AttrValue>();
|
|
252
|
+
for (const [name, node] of this._attrNodes) {
|
|
253
|
+
if (node.value !== undefined) m.set(name, node.value);
|
|
254
|
+
}
|
|
255
|
+
return m;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** True if `name` is an own (locally declared) attr — excludes inherited. */
|
|
260
|
+
ownHasAttr(name: string): boolean {
|
|
261
|
+
if (name === RESERVED_KEY_VALUE) {
|
|
262
|
+
return this._ownValueSet;
|
|
263
|
+
}
|
|
264
|
+
return this._attrNodes.has(name);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
// Effective attr accessors — the default. Own + attrs inherited via the
|
|
269
|
+
// super chain (own winning on a key conflict). Own-only access is the
|
|
270
|
+
// explicit own* opt-in above.
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Effective attrs — own + inherited via the super chain, own winning on a key conflict; cached.
|
|
275
|
+
* Do not cast to `Map` and mutate — the same reference is returned on every call
|
|
276
|
+
* after freeze, so a mutation would corrupt subsequent reads.
|
|
277
|
+
*/
|
|
278
|
+
attrs(): ReadonlyMap<string, AttrValue> {
|
|
279
|
+
return this.cached("attrs", () => this._effectiveAttrs(new Set([this])));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** Effective attr value for `name`, or undefined. */
|
|
283
|
+
attr(name: string): AttrValue | undefined {
|
|
284
|
+
return this.attrs().get(name);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** True if `name` resolves to an effective attr (own or inherited). */
|
|
288
|
+
hasAttr(name: string): boolean {
|
|
289
|
+
return this.attrs().has(name);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// ---------------------------------------------------------------------------
|
|
293
|
+
// Children
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
|
|
296
|
+
addChild(child: MetaData): void {
|
|
297
|
+
this._assertNotFrozen();
|
|
298
|
+
child._parent = this;
|
|
299
|
+
this._children.push(child);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** The node this node was added to as a child, or undefined for the tree root. */
|
|
303
|
+
get parent(): MetaData | undefined {
|
|
304
|
+
return this._parent;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/** Walk up to the top of the tree this node belongs to. */
|
|
308
|
+
root(): MetaData {
|
|
309
|
+
let node: MetaData = this;
|
|
310
|
+
while (node._parent !== undefined) {
|
|
311
|
+
node = node._parent;
|
|
312
|
+
}
|
|
313
|
+
return node;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** Own (locally declared) children — a cached frozen array; excludes children inherited via extends. */
|
|
317
|
+
ownChildren(): readonly MetaData[] {
|
|
318
|
+
return this.cached("ownChildren", () => Object.freeze([...this._children]));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** Own children whose type matches — excludes inherited. */
|
|
322
|
+
ownChildrenOfType(type: string): MetaData[] {
|
|
323
|
+
return this.ownChildren().filter((c) => c.type === type);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** Own children matching both type and subType — excludes inherited. */
|
|
327
|
+
ownChildrenOfSubType(type: string, subType: string): MetaData[] {
|
|
328
|
+
return this.ownChildren().filter((c) => c.type === type && c.subType === subType);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** First own child with matching name, or undefined — excludes inherited. */
|
|
332
|
+
ownChildByName(name: string): MetaData | undefined {
|
|
333
|
+
return this.ownChildren().find((c) => c.name === name);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** First own child matching both type and name, or undefined — excludes inherited. */
|
|
337
|
+
ownChildByTypeAndName(type: string, name: string): MetaData | undefined {
|
|
338
|
+
return this.ownChildren().find((c) => c.type === type && c.name === name);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// ---------------------------------------------------------------------------
|
|
342
|
+
// Effective child accessors — the default. Own + children inherited via the
|
|
343
|
+
// super chain (own shadowing super on a (type, name) match). Own-only access
|
|
344
|
+
// is the explicit own* opt-in above.
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
|
|
347
|
+
/** Effective children: own + inherited via the super chain, own shadowing super. Cached, frozen. */
|
|
348
|
+
children(): readonly MetaData[] {
|
|
349
|
+
return this.cached("children", () => Object.freeze(this._effectiveChildren(new Set([this]))));
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** Effective children whose type matches. */
|
|
353
|
+
childrenOfType(type: string): MetaData[] {
|
|
354
|
+
return this.children().filter((c) => c.type === type);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** Effective children matching both type and subType. */
|
|
358
|
+
childrenOfSubType(type: string, subType: string): MetaData[] {
|
|
359
|
+
return this.children().filter((c) => c.type === type && c.subType === subType);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/** First effective child with matching name, or undefined. */
|
|
363
|
+
childByName(name: string): MetaData | undefined {
|
|
364
|
+
return this.children().find((c) => c.name === name);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/** First effective child matching both type and name, or undefined. */
|
|
368
|
+
childByTypeAndName(type: string, name: string): MetaData | undefined {
|
|
369
|
+
return this.children().find((c) => c.type === type && c.name === name);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// ---------------------------------------------------------------------------
|
|
373
|
+
// Internal helpers for effective attr / child computation
|
|
374
|
+
// ---------------------------------------------------------------------------
|
|
375
|
+
|
|
376
|
+
private _effectiveAttrs(visited: Set<MetaData>): Map<string, AttrValue> {
|
|
377
|
+
const ownValues = (): Map<string, AttrValue> => {
|
|
378
|
+
const m = new Map<string, AttrValue>();
|
|
379
|
+
for (const [name, node] of this._attrNodes) {
|
|
380
|
+
if (node.value !== undefined) m.set(name, node.value);
|
|
381
|
+
}
|
|
382
|
+
return m;
|
|
383
|
+
};
|
|
384
|
+
if (this._superData === undefined || visited.has(this._superData)) {
|
|
385
|
+
return ownValues();
|
|
386
|
+
}
|
|
387
|
+
visited.add(this._superData);
|
|
388
|
+
const result = this._superData._effectiveAttrs(visited);
|
|
389
|
+
for (const [k, v] of ownValues()) {
|
|
390
|
+
result.set(k, v);
|
|
391
|
+
}
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private _effectiveChildren(visited: Set<MetaData>): MetaData[] {
|
|
396
|
+
if (this._superData === undefined || visited.has(this._superData)) {
|
|
397
|
+
return [...this._children];
|
|
398
|
+
}
|
|
399
|
+
visited.add(this._superData);
|
|
400
|
+
|
|
401
|
+
// Start from the super's effective children (already a copy from the recursive call).
|
|
402
|
+
const result = this._superData._effectiveChildren(visited);
|
|
403
|
+
|
|
404
|
+
// Track which of our own children matched (overrode) a super child position.
|
|
405
|
+
const appendQueue: MetaData[] = [];
|
|
406
|
+
|
|
407
|
+
for (const ownChild of this._children) {
|
|
408
|
+
// Find the index in result that has the same (type, name).
|
|
409
|
+
const idx = result.findIndex(
|
|
410
|
+
(sc) => sc.type === ownChild.type && sc.name === ownChild.name,
|
|
411
|
+
);
|
|
412
|
+
if (idx !== -1) {
|
|
413
|
+
// Replace the super child with our own (in-place override).
|
|
414
|
+
result[idx] = ownChild;
|
|
415
|
+
} else {
|
|
416
|
+
// No matching super child — will be appended at the end.
|
|
417
|
+
appendQueue.push(ownChild);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Append non-overriding own children.
|
|
422
|
+
result.push(...appendQueue);
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// ---------------------------------------------------------------------------
|
|
427
|
+
// Lifecycle
|
|
428
|
+
// ---------------------------------------------------------------------------
|
|
429
|
+
|
|
430
|
+
freeze(): void {
|
|
431
|
+
if (this._frozen) {
|
|
432
|
+
return; // Idempotent
|
|
433
|
+
}
|
|
434
|
+
this._frozen = true;
|
|
435
|
+
for (const child of this._children) {
|
|
436
|
+
child.freeze();
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
isFrozen(): boolean {
|
|
441
|
+
return this._frozen;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// MetaRoot — concrete node class for the type=metadata root node.
|
|
2
|
+
//
|
|
3
|
+
// Extends MetaData directly: no model wrapper, no metaOf() indirection.
|
|
4
|
+
// Children are already concrete typed nodes; accessors filter by type constant.
|
|
5
|
+
|
|
6
|
+
import { MetaData } from "./meta-data.js";
|
|
7
|
+
import { TYPE_OBJECT, TYPE_FIELD } from "./base-types.js";
|
|
8
|
+
import type { MetaObject } from "../core/object/meta-object.js";
|
|
9
|
+
import type { MetaField } from "../core/field/meta-field.js";
|
|
10
|
+
|
|
11
|
+
export class MetaRoot extends MetaData {
|
|
12
|
+
/** Object entities defined at this root level. */
|
|
13
|
+
objects(): MetaObject[] {
|
|
14
|
+
return this.cached("objects", () =>
|
|
15
|
+
this.ownChildren().filter((c): c is MetaObject => c.type === TYPE_OBJECT),
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Abstract / package-level fields defined at root (rare; e.g. shared id fields). */
|
|
20
|
+
fields(): MetaField[] {
|
|
21
|
+
return this.cached("fields", () =>
|
|
22
|
+
this.ownChildren().filter((c): c is MetaField => c.type === TYPE_FIELD),
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Find an object by name. */
|
|
27
|
+
findObject(name: string): MetaObject | undefined {
|
|
28
|
+
return this.cached(`findObject:${name}`, () => {
|
|
29
|
+
const child = this.ownChildByTypeAndName(TYPE_OBJECT, name);
|
|
30
|
+
return child !== undefined ? (child as MetaObject) : undefined;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Structural vocabulary — reserved body keys, JSON special keys, separators, wildcards, package paths.
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Reserved structural body keys (redesigned format — NOT @-prefixed, NOT attrs)
|
|
5
|
+
//
|
|
6
|
+
// Every node body is a map whose only permitted non-@ keys are these. The
|
|
7
|
+
// canonical body-key order is: name, package, extends, abstract, overlay,
|
|
8
|
+
// isArray, @-attrs (alphabetical), children.
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
export const RESERVED_KEY_NAME = "name";
|
|
12
|
+
export const RESERVED_KEY_PACKAGE = "package";
|
|
13
|
+
export const RESERVED_KEY_EXTENDS = "extends"; // the supertype reference
|
|
14
|
+
export const RESERVED_KEY_ABSTRACT = "abstract"; // true → the node is abstract
|
|
15
|
+
export const RESERVED_KEY_OVERLAY = "overlay"; // true → re-opens an existing same-named node
|
|
16
|
+
export const RESERVED_KEY_IS_ARRAY = "isArray"; // true → the node is an array
|
|
17
|
+
export const RESERVED_KEY_CHILDREN = "children";
|
|
18
|
+
|
|
19
|
+
/** attr-child-node body key carrying the typed value. */
|
|
20
|
+
export const RESERVED_KEY_VALUE = "value";
|
|
21
|
+
|
|
22
|
+
export const RESERVED_KEYS = new Set<string>([
|
|
23
|
+
RESERVED_KEY_NAME,
|
|
24
|
+
RESERVED_KEY_PACKAGE,
|
|
25
|
+
RESERVED_KEY_EXTENDS,
|
|
26
|
+
RESERVED_KEY_ABSTRACT,
|
|
27
|
+
RESERVED_KEY_OVERLAY,
|
|
28
|
+
RESERVED_KEY_IS_ARRAY,
|
|
29
|
+
RESERVED_KEY_CHILDREN,
|
|
30
|
+
RESERVED_KEY_VALUE,
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// JSON document special keys (top-level, ignored during wrapper-key detection)
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
export const JSON_KEY_SCHEMA = "$schema";
|
|
38
|
+
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Inline attribute prefix + fused type.subType key separator
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
export const ATTR_PREFIX = "@";
|
|
44
|
+
|
|
45
|
+
/** Separator fusing type and subType in a node's wrapper key (`object.entity`). */
|
|
46
|
+
export const TYPE_SUBTYPE_SEPARATOR = ".";
|
|
47
|
+
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Package path conventions
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
/** Separator between package segments and between package and name. */
|
|
53
|
+
export const PACKAGE_SEPARATOR = "::";
|
|
54
|
+
|
|
55
|
+
/** Relative-reference "go up one level" marker. */
|
|
56
|
+
export const PACKAGE_PARENT = "..";
|
|
57
|
+
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Wildcard for child-rule matching
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
export const CHILD_RULE_WILDCARD = "*";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Cross-language subtype rules for object subtypes.
|
|
2
|
+
//
|
|
3
|
+
// - value objects MUST NOT have a primary identity (error)
|
|
4
|
+
// - entity objects SHOULD have a primary identity, unless @isAbstract (warning)
|
|
5
|
+
// - base objects have no rule (template, may or may not have identity)
|
|
6
|
+
|
|
7
|
+
import type { MetaData } from "./shared/meta-data.js";
|
|
8
|
+
import { ParseError } from "./errors.js";
|
|
9
|
+
import { TYPE_OBJECT, TYPE_IDENTITY } from "./shared/base-types.js";
|
|
10
|
+
import { IDENTITY_SUBTYPE_PRIMARY } from "./core/identity/identity-constants.js";
|
|
11
|
+
import {
|
|
12
|
+
OBJECT_SUBTYPE_ENTITY,
|
|
13
|
+
OBJECT_SUBTYPE_VALUE,
|
|
14
|
+
} from "./core/object/object-constants.js";
|
|
15
|
+
|
|
16
|
+
export interface SubtypeRuleResult {
|
|
17
|
+
errors: ParseError[];
|
|
18
|
+
warnings: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function validateSubtypeRules(root: MetaData): SubtypeRuleResult {
|
|
22
|
+
const errors: ParseError[] = [];
|
|
23
|
+
const warnings: string[] = [];
|
|
24
|
+
walk(root, errors, warnings);
|
|
25
|
+
return { errors, warnings };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function walk(model: MetaData, errors: ParseError[], warnings: string[]): void {
|
|
29
|
+
if (model.type === TYPE_OBJECT) {
|
|
30
|
+
const hasPrimary = model.children().some(
|
|
31
|
+
(c) => c.type === TYPE_IDENTITY && c.subType === IDENTITY_SUBTYPE_PRIMARY,
|
|
32
|
+
);
|
|
33
|
+
if (model.subType === OBJECT_SUBTYPE_VALUE && hasPrimary) {
|
|
34
|
+
errors.push(
|
|
35
|
+
new ParseError(
|
|
36
|
+
`value object '${model.fqn()}' must not have a primary identity ` +
|
|
37
|
+
`(use subType: "entity" for records with identity)`,
|
|
38
|
+
{ code: "ERR_SUBTYPE_RULE_VIOLATION" },
|
|
39
|
+
),
|
|
40
|
+
);
|
|
41
|
+
} else if (
|
|
42
|
+
model.subType === OBJECT_SUBTYPE_ENTITY &&
|
|
43
|
+
!hasPrimary &&
|
|
44
|
+
!model.isAbstract
|
|
45
|
+
) {
|
|
46
|
+
warnings.push(
|
|
47
|
+
`entity object '${model.fqn()}' has no primary identity ` +
|
|
48
|
+
`(add an identity child or mark @isAbstract: true)`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (const child of model.ownChildren()) {
|
|
54
|
+
walk(child, errors, warnings);
|
|
55
|
+
}
|
|
56
|
+
}
|