@formspec/build 0.1.0-alpha.30 → 0.1.0-alpha.32

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/dist/internals.js CHANGED
@@ -2116,10 +2116,7 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker,
2116
2116
  if (resolvedAnchorNode === null) {
2117
2117
  return void 0;
2118
2118
  }
2119
- const propertyType = checker.getTypeOfSymbolAtLocation(
2120
- propertySymbol,
2121
- resolvedAnchorNode
2122
- );
2119
+ const propertyType = checker.getTypeOfSymbolAtLocation(propertySymbol, resolvedAnchorNode);
2123
2120
  if (propertyType.isStringLiteral()) {
2124
2121
  return propertyType.value;
2125
2122
  }
@@ -3078,14 +3075,39 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3078
3075
  collectedDiagnostics
3079
3076
  );
3080
3077
  const fieldNodeInfo = fieldInfoMap?.get(prop.name);
3078
+ const inlineFieldNodeInfo = fieldNodeInfo === void 0 ? ts3.isPropertySignature(declaration) ? analyzeInterfacePropertyToIR(
3079
+ declaration,
3080
+ checker,
3081
+ file,
3082
+ typeRegistry,
3083
+ visiting,
3084
+ collectedDiagnostics,
3085
+ type,
3086
+ metadataPolicy,
3087
+ extensionRegistry
3088
+ ) : ts3.isPropertyDeclaration(declaration) ? analyzeFieldToIR(
3089
+ declaration,
3090
+ checker,
3091
+ file,
3092
+ typeRegistry,
3093
+ visiting,
3094
+ collectedDiagnostics,
3095
+ type,
3096
+ metadataPolicy,
3097
+ extensionRegistry
3098
+ ) : null : null;
3099
+ const resolvedFieldNodeInfo = fieldNodeInfo ?? inlineFieldNodeInfo;
3100
+ const resolvedPropertyType = inlineFieldNodeInfo?.type ?? propTypeNode;
3081
3101
  properties.push({
3082
3102
  name: prop.name,
3083
- ...fieldNodeInfo?.metadata !== void 0 && { metadata: fieldNodeInfo.metadata },
3084
- type: propTypeNode,
3103
+ ...resolvedFieldNodeInfo?.metadata !== void 0 && {
3104
+ metadata: resolvedFieldNodeInfo.metadata
3105
+ },
3106
+ type: resolvedPropertyType,
3085
3107
  optional,
3086
- constraints: fieldNodeInfo?.constraints ?? [],
3087
- annotations: fieldNodeInfo?.annotations ?? [],
3088
- provenance: fieldNodeInfo?.provenance ?? provenanceForFile(file)
3108
+ constraints: resolvedFieldNodeInfo?.constraints ?? [],
3109
+ annotations: resolvedFieldNodeInfo?.annotations ?? [],
3110
+ provenance: resolvedFieldNodeInfo?.provenance ?? provenanceForFile(file)
3089
3111
  });
3090
3112
  }
3091
3113
  visiting.delete(type);
@@ -3688,9 +3710,9 @@ function collectFields(elements, properties, required, ctx) {
3688
3710
  for (const element of elements) {
3689
3711
  switch (element.kind) {
3690
3712
  case "field":
3691
- properties[getSerializedName(element.name, element.metadata)] = generateFieldSchema(element, ctx);
3713
+ properties[getSerializedFieldName(element)] = generateFieldSchema(element, ctx);
3692
3714
  if (element.required) {
3693
- required.push(getSerializedName(element.name, element.metadata));
3715
+ required.push(getSerializedFieldName(element));
3694
3716
  }
3695
3717
  break;
3696
3718
  case "group":
@@ -3761,19 +3783,21 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
3761
3783
  schema.items = applyPathTargetedConstraints(schema.items, pathConstraints, ctx, nestedType);
3762
3784
  return schema;
3763
3785
  }
3764
- const byTarget = /* @__PURE__ */ new Map();
3765
- for (const c of pathConstraints) {
3766
- const target = c.path?.segments[0];
3767
- if (!target) continue;
3768
- const group = byTarget.get(target) ?? [];
3769
- group.push(c);
3770
- byTarget.set(target, group);
3771
- }
3772
- const propertyOverrides = {};
3773
- for (const [target, constraints] of byTarget) {
3774
- const subSchema = {};
3775
- applyConstraints(subSchema, constraints, ctx);
3776
- propertyOverrides[resolveSerializedPropertyName(target, typeNode, ctx)] = subSchema;
3786
+ const propertyOverrides = buildPropertyOverrides(pathConstraints, typeNode, ctx);
3787
+ const nullableValueBranch = getNullableUnionValueSchema(schema);
3788
+ if (nullableValueBranch !== void 0) {
3789
+ const updatedNullableValueBranch = applyPathTargetedConstraints(
3790
+ nullableValueBranch,
3791
+ pathConstraints,
3792
+ ctx,
3793
+ resolveTraversableTypeNode(typeNode, ctx)
3794
+ );
3795
+ if (schema.oneOf !== void 0) {
3796
+ schema.oneOf = schema.oneOf.map(
3797
+ (branch) => branch === nullableValueBranch ? updatedNullableValueBranch : branch
3798
+ );
3799
+ }
3800
+ return schema;
3777
3801
  }
3778
3802
  if (schema.$ref) {
3779
3803
  const { $ref, ...rest } = schema;
@@ -3788,7 +3812,7 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
3788
3812
  const missingOverrides = {};
3789
3813
  for (const [target, overrideSchema] of Object.entries(propertyOverrides)) {
3790
3814
  if (schema.properties[target]) {
3791
- Object.assign(schema.properties[target], overrideSchema);
3815
+ mergeSchemaOverride(schema.properties[target], overrideSchema);
3792
3816
  } else {
3793
3817
  missingOverrides[target] = overrideSchema;
3794
3818
  }
@@ -3862,7 +3886,7 @@ function generateObjectType(type, ctx) {
3862
3886
  const properties = {};
3863
3887
  const required = [];
3864
3888
  for (const prop of type.properties) {
3865
- const propertyName = getSerializedName(prop.name, prop.metadata);
3889
+ const propertyName = getSerializedObjectPropertyName(prop);
3866
3890
  properties[propertyName] = generatePropertySchema(prop, ctx);
3867
3891
  if (!prop.optional) {
3868
3892
  required.push(propertyName);
@@ -3916,7 +3940,16 @@ function isNullableUnion(type) {
3916
3940
  return nullCount === 1;
3917
3941
  }
3918
3942
  function generateReferenceType(type, ctx) {
3919
- return { $ref: `#/$defs/${ctx.typeNameMap[type.name] ?? type.name}` };
3943
+ return { $ref: `#/$defs/${getSerializedTypeName(type.name, ctx)}` };
3944
+ }
3945
+ function getSerializedFieldName(field) {
3946
+ return getSerializedName(field.name, field.metadata);
3947
+ }
3948
+ function getSerializedObjectPropertyName(property) {
3949
+ return getSerializedName(property.name, property.metadata);
3950
+ }
3951
+ function getSerializedTypeName(logicalName, ctx) {
3952
+ return ctx.typeNameMap[logicalName] ?? logicalName;
3920
3953
  }
3921
3954
  function applyResolvedMetadata(schema, metadata) {
3922
3955
  const displayName = getDisplayName(metadata);
@@ -3927,17 +3960,148 @@ function applyResolvedMetadata(schema, metadata) {
3927
3960
  function resolveReferencedType(type, ctx) {
3928
3961
  return ctx.typeRegistry[type.name]?.type;
3929
3962
  }
3963
+ function dereferenceTypeNode(typeNode, ctx) {
3964
+ if (typeNode?.kind !== "reference") {
3965
+ return typeNode;
3966
+ }
3967
+ return resolveReferencedType(typeNode, ctx);
3968
+ }
3969
+ function unwrapNullableTypeNode(typeNode) {
3970
+ if (typeNode?.kind !== "union" || !isNullableUnion(typeNode)) {
3971
+ return typeNode;
3972
+ }
3973
+ return typeNode.members.find(
3974
+ (member) => !(member.kind === "primitive" && member.primitiveKind === "null")
3975
+ );
3976
+ }
3977
+ function resolveTraversableTypeNode(typeNode, ctx) {
3978
+ const dereferenced = dereferenceTypeNode(typeNode, ctx);
3979
+ const unwrapped = unwrapNullableTypeNode(dereferenced);
3980
+ if (unwrapped !== dereferenced) {
3981
+ return resolveTraversableTypeNode(unwrapped, ctx);
3982
+ }
3983
+ return dereferenced;
3984
+ }
3930
3985
  function resolveSerializedPropertyName(logicalName, typeNode, ctx) {
3931
- if (typeNode?.kind === "object") {
3932
- const property = typeNode.properties.find((candidate) => candidate.name === logicalName);
3933
- return property === void 0 ? logicalName : getSerializedName(property.name, property.metadata);
3986
+ const effectiveType = resolveTraversableTypeNode(typeNode, ctx);
3987
+ if (effectiveType?.kind === "array") {
3988
+ return resolveSerializedPropertyName(logicalName, effectiveType.items, ctx);
3934
3989
  }
3935
- if (typeNode?.kind === "reference") {
3936
- const referencedType = resolveReferencedType(typeNode, ctx);
3937
- return referencedType === void 0 ? logicalName : resolveSerializedPropertyName(logicalName, referencedType, ctx);
3990
+ if (effectiveType?.kind === "object") {
3991
+ const property = effectiveType.properties.find((candidate) => candidate.name === logicalName);
3992
+ return property === void 0 ? logicalName : getSerializedObjectPropertyName(property);
3938
3993
  }
3939
3994
  return logicalName;
3940
3995
  }
3996
+ function resolveTargetTypeNode(logicalName, typeNode, ctx) {
3997
+ const effectiveType = resolveTraversableTypeNode(typeNode, ctx);
3998
+ if (effectiveType?.kind === "array") {
3999
+ return resolveTargetTypeNode(logicalName, effectiveType.items, ctx);
4000
+ }
4001
+ if (effectiveType?.kind !== "object") {
4002
+ return void 0;
4003
+ }
4004
+ return effectiveType.properties.find((candidate) => candidate.name === logicalName)?.type;
4005
+ }
4006
+ function buildPropertyOverrides(pathConstraints, typeNode, ctx) {
4007
+ const byTarget = /* @__PURE__ */ new Map();
4008
+ for (const constraint of pathConstraints) {
4009
+ const target = constraint.path?.segments[0];
4010
+ if (!target) {
4011
+ continue;
4012
+ }
4013
+ const grouped = byTarget.get(target) ?? [];
4014
+ grouped.push(constraint);
4015
+ byTarget.set(target, grouped);
4016
+ }
4017
+ const overrides = {};
4018
+ for (const [target, constraints] of byTarget) {
4019
+ overrides[resolveSerializedPropertyName(target, typeNode, ctx)] = buildPathOverrideSchema(
4020
+ constraints.map(stripLeadingPathSegment),
4021
+ resolveTargetTypeNode(target, typeNode, ctx),
4022
+ ctx
4023
+ );
4024
+ }
4025
+ return overrides;
4026
+ }
4027
+ function buildPathOverrideSchema(constraints, typeNode, ctx) {
4028
+ const schema = {};
4029
+ const directConstraints = [];
4030
+ const nestedConstraints = [];
4031
+ for (const constraint of constraints) {
4032
+ if (constraint.path === void 0 || constraint.path.segments.length === 0) {
4033
+ directConstraints.push(constraint);
4034
+ } else {
4035
+ nestedConstraints.push(constraint);
4036
+ }
4037
+ }
4038
+ applyConstraints(schema, directConstraints, ctx);
4039
+ if (nestedConstraints.length === 0) {
4040
+ return schema;
4041
+ }
4042
+ const effectiveType = resolveTraversableTypeNode(typeNode, ctx);
4043
+ if (effectiveType?.kind === "array") {
4044
+ schema.items = buildPathOverrideSchema(nestedConstraints, effectiveType.items, ctx);
4045
+ return schema;
4046
+ }
4047
+ schema.properties = buildPropertyOverrides(nestedConstraints, effectiveType, ctx);
4048
+ return schema;
4049
+ }
4050
+ function mergeSchemaOverride(target, override) {
4051
+ const nullableValueBranch = getNullableUnionValueSchema(target);
4052
+ if (nullableValueBranch !== void 0) {
4053
+ mergeSchemaOverride(nullableValueBranch, override);
4054
+ return;
4055
+ }
4056
+ if (override.properties !== void 0) {
4057
+ const mergedProperties = target.properties ?? {};
4058
+ for (const [name, propertyOverride] of Object.entries(override.properties)) {
4059
+ const existing = mergedProperties[name];
4060
+ if (existing === void 0) {
4061
+ mergedProperties[name] = propertyOverride;
4062
+ } else {
4063
+ mergeSchemaOverride(existing, propertyOverride);
4064
+ }
4065
+ }
4066
+ target.properties = mergedProperties;
4067
+ }
4068
+ if (override.items !== void 0) {
4069
+ if (target.items === void 0) {
4070
+ target.items = override.items;
4071
+ } else {
4072
+ mergeSchemaOverride(target.items, override.items);
4073
+ }
4074
+ }
4075
+ for (const [key, value] of Object.entries(override)) {
4076
+ if (key === "properties" || key === "items") {
4077
+ continue;
4078
+ }
4079
+ target[key] = value;
4080
+ }
4081
+ }
4082
+ function stripLeadingPathSegment(constraint) {
4083
+ const segments = constraint.path?.segments;
4084
+ if (segments === void 0 || segments.length === 0) {
4085
+ return constraint;
4086
+ }
4087
+ const [, ...rest] = segments;
4088
+ if (rest.length === 0) {
4089
+ const { path: _path, ...stripped } = constraint;
4090
+ return stripped;
4091
+ }
4092
+ return {
4093
+ ...constraint,
4094
+ path: { segments: rest }
4095
+ };
4096
+ }
4097
+ function getNullableUnionValueSchema(schema) {
4098
+ if (schema.oneOf?.length !== 2) {
4099
+ return void 0;
4100
+ }
4101
+ const valueSchema = schema.oneOf.find((branch) => branch.type !== "null");
4102
+ const nullSchema = schema.oneOf.find((branch) => branch.type === "null");
4103
+ return valueSchema !== void 0 && nullSchema !== void 0 ? valueSchema : void 0;
4104
+ }
3941
4105
  function generateDynamicType(type) {
3942
4106
  if (type.dynamicKind === "enum") {
3943
4107
  const schema = {