type-crafter 0.6.0 → 0.7.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/dist/index.js CHANGED
@@ -3533,9 +3533,20 @@ function decodeTypes(rawInput) {
3533
3533
  }
3534
3534
  return null;
3535
3535
  }
3536
+ function decodeAdditionalPropertiesKeyType(rawInput) {
3537
+ if (typeof rawInput === 'string') {
3538
+ switch (rawInput) {
3539
+ case 'string':
3540
+ case 'number':
3541
+ return rawInput;
3542
+ }
3543
+ }
3544
+ return null;
3545
+ }
3536
3546
  function decodeTypeInfo(rawInput) {
3537
3547
  if (isJSON(rawInput)) {
3538
3548
  const _type = decodeTypeDataType(rawInput.type);
3549
+ const additionalProperties = decodeAdditionalProperties(rawInput.additionalProperties);
3539
3550
  const result = {
3540
3551
  type: _type,
3541
3552
  required: decodeArray(rawInput.required, decodeString),
@@ -3547,6 +3558,7 @@ function decodeTypeInfo(rawInput) {
3547
3558
  description: decodeString(rawInput.description),
3548
3559
  example: decodeString(rawInput.example) ?? decodeNumber(rawInput.example),
3549
3560
  oneOf: decodeArray(rawInput.oneOf, decodeTypeInfo),
3561
+ additionalProperties,
3550
3562
  enum: _type === 'string'
3551
3563
  ? decodeArray(rawInput.enum, decodeString)
3552
3564
  : _type === 'number'
@@ -3557,6 +3569,28 @@ function decodeTypeInfo(rawInput) {
3557
3569
  }
3558
3570
  return null;
3559
3571
  }
3572
+ function decodeAdditionalProperties(rawInput) {
3573
+ return (decodeKeyedAdditionalProperties(rawInput) ?? decodeTypeInfo(rawInput) ?? decodeBoolean(rawInput));
3574
+ }
3575
+ function decodeKeyedAdditionalProperties(rawInput) {
3576
+ if (isJSON(rawInput)) {
3577
+ const keyType = decodeAdditionalPropertiesKeyType(rawInput.keyType);
3578
+ const valueType = decodeTypeInfo(rawInput.valueType);
3579
+ if (keyType !== null && valueType !== null) {
3580
+ return {
3581
+ keyType,
3582
+ valueType
3583
+ };
3584
+ }
3585
+ }
3586
+ return null;
3587
+ }
3588
+ function valueIsKeyedAdditionalProperties(value) {
3589
+ return decodeKeyedAdditionalProperties(value) !== null;
3590
+ }
3591
+ function valueIsTypeInfo(value) {
3592
+ return decodeTypeInfo(value) !== null;
3593
+ }
3560
3594
  function decodeTypeProperties(rawInput) {
3561
3595
  if (isJSON(rawInput)) {
3562
3596
  const result = {};
@@ -19647,6 +19681,20 @@ function fillPatterns(input, patterns) {
19647
19681
  return result;
19648
19682
  }
19649
19683
 
19684
+ const placeholderTypeInfo = {
19685
+ required: null,
19686
+ type: null,
19687
+ format: null,
19688
+ items: null,
19689
+ properties: null,
19690
+ $ref: null,
19691
+ oneOf: null,
19692
+ enum: null,
19693
+ additionalProperties: null,
19694
+ summary: null,
19695
+ description: null,
19696
+ example: null
19697
+ };
19650
19698
  /**
19651
19699
  * @description Generates the primitive type for the unit attribute in the spec.
19652
19700
  * @param typeName { string }
@@ -19688,6 +19736,39 @@ function getPrimitiveType(typeName, typeInfo) {
19688
19736
  result.primitives.add(languageDataType);
19689
19737
  return result;
19690
19738
  }
19739
+ async function generateAdditionalPropertiesType(typeName, typeInfo, parentTypes) {
19740
+ let result = null;
19741
+ const stringKeyType = getPrimitiveType(typeName, {
19742
+ ...placeholderTypeInfo,
19743
+ type: 'string'
19744
+ }).templateInput.type;
19745
+ if (typeof typeInfo.additionalProperties === 'boolean') {
19746
+ result = {
19747
+ keyType: stringKeyType,
19748
+ valueType: getPrimitiveType(typeName, {
19749
+ ...placeholderTypeInfo,
19750
+ type: 'unknown'
19751
+ }).templateInput.type
19752
+ };
19753
+ }
19754
+ else if (valueIsKeyedAdditionalProperties(typeInfo.additionalProperties)) {
19755
+ result = {
19756
+ keyType: getPrimitiveType(typeName, {
19757
+ ...placeholderTypeInfo,
19758
+ type: typeInfo.additionalProperties.keyType
19759
+ }).templateInput.type,
19760
+ valueType: (await generateType(typeName + 'ValueType', typeInfo.additionalProperties.valueType, parentTypes)).templateInput.type
19761
+ };
19762
+ }
19763
+ else if (valueIsTypeInfo(typeInfo.additionalProperties)) {
19764
+ const valueType = await generateType(typeName + 'ValueType', typeInfo.additionalProperties, parentTypes);
19765
+ result = {
19766
+ keyType: stringKeyType,
19767
+ valueType: valueType.templateInput.type
19768
+ };
19769
+ }
19770
+ return result;
19771
+ }
19691
19772
  async function generateObjectType(typeName, typeInfo, parentTypes) {
19692
19773
  const templateInput = {
19693
19774
  typeName,
@@ -19708,7 +19789,10 @@ async function generateObjectType(typeName, typeInfo, parentTypes) {
19708
19789
  const reference = propertyDetails.$ref ?? null;
19709
19790
  const enumValues = propertyDetails.enum ?? null;
19710
19791
  // Throwing error in case neither property type nor reference to a different type is present
19711
- if (propertyType === null && reference === null && propertyDetails.oneOf === null) {
19792
+ if (propertyType === null &&
19793
+ reference === null &&
19794
+ propertyDetails.oneOf === null &&
19795
+ propertyDetails.additionalProperties === null) {
19712
19796
  throw new InvalidSpecFileError('Invalid property type for: ' + typeName + '.' + propertyName);
19713
19797
  }
19714
19798
  const primitiveType = propertyType ?? 'object';
@@ -19726,7 +19810,7 @@ async function generateObjectType(typeName, typeInfo, parentTypes) {
19726
19810
  }
19727
19811
  else if (enumValues !== null) {
19728
19812
  const enumName = toPascalCase(propertyName) + 'Enum';
19729
- dynamicGeneratedType = generateEnumType(enumName, propertyDetails).content;
19813
+ dynamicGeneratedType += generateEnumType(enumName, propertyDetails).content;
19730
19814
  languageDataType = enumName;
19731
19815
  }
19732
19816
  else if (propertyType === 'array') {
@@ -19748,7 +19832,7 @@ async function generateObjectType(typeName, typeInfo, parentTypes) {
19748
19832
  languageDataType = primitiveTypeGenOutput.templateInput.type;
19749
19833
  primitives.push(...primitiveTypeGenOutput.primitives);
19750
19834
  references.push(...primitiveTypeGenOutput.references);
19751
- dynamicGeneratedType = primitiveTypeGenOutput.content;
19835
+ dynamicGeneratedType += primitiveTypeGenOutput.content;
19752
19836
  }
19753
19837
  if (languageDataType === null) {
19754
19838
  throw new InvalidSpecFileError(`Invalid language data type for: ${typeName}.${propertyName}`);
@@ -19767,6 +19851,11 @@ async function generateObjectType(typeName, typeInfo, parentTypes) {
19767
19851
  }
19768
19852
  };
19769
19853
  }
19854
+ // Generating additional property types
19855
+ const additionalProperties = await generateAdditionalPropertiesType(typeName + 'AdditionalProperty', typeInfo, parentTypes);
19856
+ if (additionalProperties !== null) {
19857
+ templateInput.additionalProperties = additionalProperties;
19858
+ }
19770
19859
  const result = {
19771
19860
  content: Runtime.getObjectTemplate()(templateInput) +
19772
19861
  (recursiveTypeGenOutput?.content ?? '') +
@@ -20089,7 +20178,7 @@ async function writeTypesToFiles(config, types, folderName = '') {
20089
20178
  // Filtering references for writing types to files; Done for types.writerMode: Files
20090
20179
  // Maybe a hack. But it works for now
20091
20180
  // Fix this later
20092
- const filterReferences = folderName !== '';
20181
+ const filterReferences = folderName !== '' && Runtime.getConfig().output.writerMode.groupedTypes !== 'FolderWithFiles';
20093
20182
  const typeNames = Object.keys(types);
20094
20183
  for (const typeName in types) {
20095
20184
  const typeData = types[typeName];
@@ -20325,15 +20414,15 @@ async function runner(language, inputFilePath, outputDirectory, _typesWriterMode
20325
20414
  }
20326
20415
  }
20327
20416
  greeting();
20328
- const program = new Command().version('0.6.0');
20417
+ const program = new Command().version('0.7.0');
20329
20418
  program
20330
20419
  .command('generate')
20331
20420
  .description('Generate types for your language from a type spec file')
20332
20421
  .argument('<outputLanguage>', 'Language to generate types for')
20333
20422
  .argument('<inputFilePath>', 'Path to the input spec file')
20334
20423
  .argument('<outputDirectory>', 'Path to the output file')
20335
- .argument('[typesWriterMode]', 'Writer mode for types', 'Files')
20336
- .argument('[groupedTypesWriterMode]', 'Writer mode for grouped types', 'FolderWithFiles')
20424
+ .argument('[typesWriterMode]', 'Writer mode for types', 'SingleFile')
20425
+ .argument('[groupedTypesWriterMode]', 'Writer mode for grouped types', 'SingleFile')
20337
20426
  .action(runner);
20338
20427
  program.parse();
20339
20428
 
@@ -21,4 +21,7 @@ export type {{typeName}} = {
21
21
  */
22
22
  {{{jsonKey @key}}}: {{{this.type}}}{{#unless this.required}} | null{{/unless}};
23
23
  {{/each}}
24
+ {{#if additionalProperties}}
25
+ [keys: {{jsonKey additionalProperties.keyType}}]: {{additionalProperties.valueType}};
26
+ {{/if}}
24
27
  };
@@ -21,6 +21,9 @@ export type {{typeName}} = {
21
21
  */
22
22
  {{{jsonKey @key}}}: {{{this.type}}}{{#unless this.required}} | null{{/unless}};
23
23
  {{/each}}
24
+ {{#if additionalProperties}}
25
+ [keys: {{jsonKey additionalProperties.keyType}}]: {{additionalProperties.valueType}};
26
+ {{/if}}
24
27
  };
25
28
 
26
29
  export function decode{{typeName}}(rawInput: unknown): {{typeName}} | null {
@@ -40,6 +43,9 @@ export function decode{{typeName}}(rawInput: unknown): {{typeName}} | null {
40
43
  {{/if}}
41
44
 
42
45
  return {
46
+ {{#if additionalProperties}}
47
+ ...rawInput,
48
+ {{/if}}
43
49
  {{#each properties}}
44
50
  {{{jsonKey @key}}}: decoded{{{variableName @key}}},
45
51
  {{/each}}
@@ -1,9 +1,12 @@
1
- import type { GroupRef, EnumTemplateInput, GroupedTypesWriterMode, ObjectTemplateInputProperties, SpecFileData, TypeInfo, Types, TypesWriterMode, GroupTypesData } from '.';
1
+ import type { GroupRef, EnumTemplateInput, GroupedTypesWriterMode, ObjectTemplateInputProperties, SpecFileData, TypeInfo, Types, TypesWriterMode, GroupTypesData, KeyedAdditionalProperties, AdditionalPropertiesKeyType } from '.';
2
2
  export declare function decodeGroupedTypesWriterMode(rawInput: unknown): GroupedTypesWriterMode | null;
3
3
  export declare function decodeTypesWriterMode(rawInput: unknown): TypesWriterMode | null;
4
4
  export declare function decodeSpecFileData(rawInput: unknown): SpecFileData | null;
5
5
  export declare function valueIsGroupRef(value: GroupTypesData): value is GroupRef;
6
6
  export declare function decodeTypes(rawInput: unknown): Types | null;
7
+ export declare function decodeAdditionalPropertiesKeyType(rawInput: unknown): AdditionalPropertiesKeyType | null;
7
8
  export declare function decodeTypeInfo(rawInput: unknown): TypeInfo | null;
9
+ export declare function valueIsKeyedAdditionalProperties(value: unknown): value is KeyedAdditionalProperties;
10
+ export declare function valueIsTypeInfo(value: unknown): value is TypeInfo;
8
11
  export declare function decodeObjectTemplateInputProperties(rawInput: unknown): ObjectTemplateInputProperties | null;
9
12
  export declare function decodeEnumTemplateInput(rawInput: unknown): EnumTemplateInput | null;
@@ -79,7 +79,14 @@ export type TypeInfo = TypeDescriptors & {
79
79
  $ref: string | null;
80
80
  oneOf: TypeInfo[] | null;
81
81
  enum: string[] | number[] | null;
82
+ additionalProperties: AdditionalProperties | null;
82
83
  };
84
+ export type AdditionalProperties = KeyedAdditionalProperties | TypeInfo | boolean;
85
+ export type KeyedAdditionalProperties = {
86
+ keyType: AdditionalPropertiesKeyType;
87
+ valueType: TypeInfo;
88
+ };
89
+ export type AdditionalPropertiesKeyType = 'string' | 'number';
83
90
  type PropertyName = string;
84
91
  export type TypeProperties = Record<PropertyName, TypeInfo>;
85
92
  export type TypeDataType = 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'unknown';
@@ -92,6 +99,7 @@ export type ObjectTemplateInput = TypeDescriptors & {
92
99
  typeName: string;
93
100
  type: string;
94
101
  properties: ObjectTemplateInputProperties;
102
+ additionalProperties?: AdditionalPropertiesTemplateInput;
95
103
  };
96
104
  export type ObjectTemplateInputProperties = Record<PropertyName, ObjectTemplateInputProperty>;
97
105
  export type ObjectTemplateInputProperty = TypeDescriptors & {
@@ -101,6 +109,10 @@ export type ObjectTemplateInputProperty = TypeDescriptors & {
101
109
  primitiveType: string;
102
110
  composerType: string | null;
103
111
  };
112
+ export type AdditionalPropertiesTemplateInput = {
113
+ keyType: string;
114
+ valueType: string;
115
+ };
104
116
  export type ExporterModuleTemplateInput = {
105
117
  modules: string[];
106
118
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-crafter",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "A tool to generate types from a yaml schema for any language",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",