@arcteninc/core 0.0.53 → 0.0.55

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcteninc/core",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -46,12 +46,12 @@
46
46
  "ajv": "^8.17.1",
47
47
  "react": "^19.2.0",
48
48
  "react-dom": "^19.2.0",
49
- "ts-json-schema-generator": "^2.4.0",
50
- "typescript": "^5.9.3",
51
49
  "vite": "^7.1.12",
52
50
  "vite-plugin-dts": "^4.5.4"
53
51
  },
54
52
  "dependencies": {
53
+ "ts-json-schema-generator": "^2.4.0",
54
+ "typescript": "^5.9.3",
55
55
  "@ai-sdk/openai": "^3.0.0-beta.47",
56
56
  "@ai-sdk/react": "^3.0.0-beta.92",
57
57
  "@emotion/is-prop-valid": "^1.4.0",
@@ -731,54 +731,18 @@ function serializeTypeCustom(
731
731
  }
732
732
 
733
733
  // Build the schema for this type
734
- // For interfaces, get properties from both the type and the declaration
735
734
  const props = checker.getPropertiesOfType(type);
736
- const properties: Record<string, JsonSchemaProperty> = {};
737
- const required: string[] = [];
738
-
739
- // Extract properties from the interface/type alias declaration
740
- if (ts.isInterfaceDeclaration(firstDecl)) {
741
- for (const member of firstDecl.members) {
742
- if (ts.isPropertySignature(member) && ts.isIdentifier(member.name)) {
743
- const propName = member.name.text;
744
- const isOptional = member.questionToken !== undefined;
745
-
746
- if (member.type) {
747
- const propType = checker.getTypeFromTypeNode(member.type);
748
- const propResult = serializeTypeCustom(propType, checker, defs, visited, depth + 1);
749
- properties[propName] = propResult.schema;
750
-
751
- if (!isOptional && !propResult.isOptional) {
752
- required.push(propName);
753
- }
754
- }
755
- }
756
- }
757
- } else if (ts.isTypeAliasDeclaration(firstDecl) && firstDecl.type) {
758
- // For type aliases, resolve the underlying type
759
- const underlyingType = checker.getTypeFromTypeNode(firstDecl.type);
760
- if (underlyingType.flags & ts.TypeFlags.Object) {
761
- const aliasProps = checker.getPropertiesOfType(underlyingType);
762
- for (const prop of aliasProps) {
763
- const propName = prop.getName();
764
- const propType = checker.getTypeOfSymbolAtLocation(prop, prop.valueDeclaration || prop.declarations?.[0] || null as any);
765
- const isOptional = (prop.flags & ts.SymbolFlags.Optional) !== 0;
766
-
767
- const propResult = serializeTypeCustom(propType, checker, defs, visited, depth + 1);
768
- properties[propName] = propResult.schema;
769
-
770
- if (!isOptional && !propResult.isOptional) {
771
- required.push(propName);
772
- }
773
- }
774
- }
775
- } else if (props.length > 0) {
776
- // Fallback: use getPropertiesOfType if declaration parsing didn't work
735
+ if (props.length > 0) {
736
+ const properties: Record<string, JsonSchemaProperty> = {};
737
+ const required: string[] = [];
738
+
739
+ // Use the same visited set for properties to detect recursion
777
740
  for (const prop of props) {
778
741
  const propName = prop.getName();
779
- const propType = checker.getTypeOfSymbolAtLocation(prop, prop.valueDeclaration || prop.declarations?.[0] || null as any);
742
+ const propType = checker.getTypeOfSymbolAtLocation(prop, prop.valueDeclaration || prop.declarations?.[0] || checker.getDeclaredTypeOfSymbol(prop).symbol?.valueDeclaration || null as any);
780
743
  const isOptional = (prop.flags & ts.SymbolFlags.Optional) !== 0;
781
744
 
745
+ // Recursively serialize the property type (will detect recursion via visited set)
782
746
  const propResult = serializeTypeCustom(propType, checker, defs, visited, depth + 1);
783
747
  properties[propName] = propResult.schema;
784
748
 
@@ -786,15 +750,15 @@ function serializeTypeCustom(
786
750
  required.push(propName);
787
751
  }
788
752
  }
753
+
754
+ // Update the placeholder with the actual schema
755
+ defs[defsKey] = {
756
+ type: 'object',
757
+ properties,
758
+ ...(required.length > 0 && { required })
759
+ };
789
760
  }
790
761
 
791
- // Update the placeholder with the actual schema (even if empty, to avoid infinite loops)
792
- defs[defsKey] = {
793
- type: 'object',
794
- properties,
795
- ...(required.length > 0 && { required })
796
- };
797
-
798
762
  // Return reference
799
763
  return { isOptional: false, schema: { $ref: `#/$defs/${defsKey}` } };
800
764
  }
@@ -860,6 +824,73 @@ function serializeTypeCustom(
860
824
  }
861
825
  }
862
826
 
827
+ // Handle arrays
828
+ if (checker.isArrayType(type)) {
829
+ const typeArgs = (type as ts.TypeReference).typeArguments;
830
+ if (typeArgs && typeArgs.length > 0) {
831
+ const itemResult = serializeTypeCustom(typeArgs[0], checker, defs, visited, depth + 1);
832
+ return {
833
+ isOptional: false,
834
+ schema: { type: 'array', items: itemResult.schema }
835
+ };
836
+ }
837
+ return { isOptional: false, schema: { type: 'array' } };
838
+ }
839
+
840
+ // Handle union types (like "file" | "folder" or string | null)
841
+ if (type.isUnion()) {
842
+ const types = type.types;
843
+ const hasNull = types.some(t => t.flags & ts.TypeFlags.Null);
844
+ const hasUndefined = types.some(t => t.flags & ts.TypeFlags.Undefined);
845
+ const nonNullUndefinedTypes = types.filter(
846
+ t => !(t.flags & ts.TypeFlags.Null) && !(t.flags & ts.TypeFlags.Undefined)
847
+ );
848
+
849
+ // If it's just T | undefined, make it optional
850
+ if (hasUndefined && nonNullUndefinedTypes.length === 1 && !hasNull) {
851
+ const result = serializeTypeCustom(nonNullUndefinedTypes[0], checker, defs, visited, depth + 1);
852
+ return { isOptional: true, schema: result.schema };
853
+ }
854
+
855
+ // Check if union is all string/number literals (enum-like union)
856
+ const allStringLiterals = nonNullUndefinedTypes.every(t => t.flags & ts.TypeFlags.StringLiteral);
857
+ const allNumberLiterals = nonNullUndefinedTypes.every(t => t.flags & ts.TypeFlags.NumberLiteral);
858
+
859
+ if (allStringLiterals && nonNullUndefinedTypes.length > 0) {
860
+ const enumValues = nonNullUndefinedTypes.map(t => {
861
+ const literalType = t as ts.StringLiteralType;
862
+ return literalType.value;
863
+ });
864
+ const schema: JsonSchemaProperty = { enum: enumValues };
865
+ return { isOptional: hasNull || hasUndefined, schema };
866
+ }
867
+
868
+ if (allNumberLiterals && nonNullUndefinedTypes.length > 0) {
869
+ const enumValues = nonNullUndefinedTypes.map(t => {
870
+ const literalType = t as ts.NumberLiteralType;
871
+ return literalType.value;
872
+ });
873
+ const schema: JsonSchemaProperty = { enum: enumValues };
874
+ return { isOptional: hasNull || hasUndefined, schema };
875
+ }
876
+
877
+ // Build anyOf for unions
878
+ if (nonNullUndefinedTypes.length > 0 || hasNull) {
879
+ const anyOf: JsonSchemaProperty[] = [];
880
+ if (hasNull || hasUndefined) {
881
+ anyOf.push({ type: 'null' });
882
+ }
883
+ for (const unionType of nonNullUndefinedTypes) {
884
+ const result = serializeTypeCustom(unionType, checker, defs, visited, depth + 1);
885
+ anyOf.push(result.schema);
886
+ }
887
+ if (anyOf.length === 1) {
888
+ return { isOptional: hasNull || hasUndefined, schema: anyOf[0] };
889
+ }
890
+ return { isOptional: false, schema: { anyOf } };
891
+ }
892
+ }
893
+
863
894
  // Handle object types with properties (anonymous types)
864
895
  if (type.flags & ts.TypeFlags.Object) {
865
896
  const props = checker.getPropertiesOfType(type);
@@ -873,7 +904,7 @@ function serializeTypeCustom(
873
904
  const isOptional = (prop.flags & ts.SymbolFlags.Optional) !== 0;
874
905
 
875
906
  // Recursively serialize the property type
876
- const propResult = serializeTypeCustom(propType, checker, defs, new Set(visited), depth + 1);
907
+ const propResult = serializeTypeCustom(propType, checker, defs, visited, depth + 1);
877
908
  properties[propName] = propResult.schema;
878
909
 
879
910
  if (!isOptional && !propResult.isOptional) {