type-crafter 0.2.1 → 0.4.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
@@ -10665,6 +10665,17 @@ function __decodeString(value) {
10665
10665
  }
10666
10666
  return errorDelimiter;
10667
10667
  }
10668
+ /**
10669
+ * @description A function which attempts to safely cast any value to a valid number
10670
+ * @param value Value with unknown type
10671
+ * @returns Attempts to convert the passed value to a valid number, returns null in case cast fails
10672
+ */
10673
+ function decodeNumber(value) {
10674
+ if (typeof value === 'number') {
10675
+ return value;
10676
+ }
10677
+ return null;
10678
+ }
10668
10679
  /**
10669
10680
  * @description A function which attempts to safely cast any value to a valid boolean
10670
10681
  * @param value Value with unknown type
@@ -10809,13 +10820,22 @@ function decodeTypes(rawInput) {
10809
10820
  }
10810
10821
  function decodeTypeInfo(rawInput) {
10811
10822
  if (isJSON(rawInput)) {
10823
+ const _type = decodeTypeDataType(rawInput.type);
10812
10824
  const result = {
10813
- type: decodeTypeDataType(rawInput.type),
10825
+ type: _type,
10814
10826
  required: decodeArray(rawInput.required, decodeString),
10815
10827
  properties: decodeTypeProperties(rawInput.properties),
10816
10828
  items: decodeTypeInfo(rawInput.items),
10817
10829
  format: decodeString(rawInput.format),
10818
- $ref: decodeString(rawInput.$ref)
10830
+ $ref: decodeString(rawInput.$ref),
10831
+ description: decodeString(rawInput.description),
10832
+ example: decodeString(rawInput.example) ?? decodeNumber(rawInput.example),
10833
+ oneOf: decodeArray(rawInput.oneOf, decodeTypeInfo),
10834
+ enum: _type === 'string'
10835
+ ? decodeArray(rawInput.enum, decodeString)
10836
+ : _type === 'number'
10837
+ ? decodeArray(rawInput.enum, decodeNumber)
10838
+ : null
10819
10839
  };
10820
10840
  return result;
10821
10841
  }
@@ -10860,13 +10880,17 @@ function decodeObjectTemplateInputProperty(rawInput) {
10860
10880
  const referenced = decodeBoolean(rawInput.referenced);
10861
10881
  const primitiveType = decodeString(rawInput.primitiveType);
10862
10882
  const composerType = decodeString(rawInput.composerType);
10883
+ const example = decodeString(rawInput.example) ?? decodeNumber(rawInput.example);
10884
+ const description = decodeString(rawInput.description);
10863
10885
  if (required !== null && _type !== null && referenced !== null && primitiveType !== null) {
10864
10886
  return {
10865
10887
  type: _type,
10866
10888
  required,
10867
10889
  referenced,
10868
10890
  primitiveType,
10869
- composerType
10891
+ composerType,
10892
+ example,
10893
+ description
10870
10894
  };
10871
10895
  }
10872
10896
  }
@@ -19204,6 +19228,8 @@ let specFileData = null;
19204
19228
  let objectSyntaxTemplate = null;
19205
19229
  let exporterModuleSyntaxTemplate = null;
19206
19230
  let typesFileSyntaxTemplate = null;
19231
+ let oneOfSyntaxTemplate = null;
19232
+ let enumSyntaxTemplate = null;
19207
19233
  let expectedOutputFiles = null;
19208
19234
  function setConfig(newConfig) {
19209
19235
  config$2 = newConfig;
@@ -19228,6 +19254,8 @@ function compileTemplates() {
19228
19254
  objectSyntaxTemplate = Handlebars.compile(config.template.objectSyntax);
19229
19255
  exporterModuleSyntaxTemplate = Handlebars.compile(config.template.exporterModuleSyntax);
19230
19256
  typesFileSyntaxTemplate = Handlebars.compile(config.template.typesFileSyntax);
19257
+ enumSyntaxTemplate = Handlebars.compile(config.template.enumSyntax);
19258
+ oneOfSyntaxTemplate = Handlebars.compile(config.template.oneOfSyntax);
19231
19259
  }
19232
19260
  function getObjectTemplate() {
19233
19261
  if (objectSyntaxTemplate === null) {
@@ -19247,6 +19275,18 @@ function getTypesFileTemplate() {
19247
19275
  }
19248
19276
  return typesFileSyntaxTemplate;
19249
19277
  }
19278
+ function getEnumTemplate() {
19279
+ if (enumSyntaxTemplate === null) {
19280
+ throw new RuntimeError('Enum template not compiled!');
19281
+ }
19282
+ return enumSyntaxTemplate;
19283
+ }
19284
+ function getOneOfTemplate() {
19285
+ if (oneOfSyntaxTemplate === null) {
19286
+ throw new RuntimeError('OneOf template not compiled!');
19287
+ }
19288
+ return oneOfSyntaxTemplate;
19289
+ }
19250
19290
  function setExpectedOutputFiles(newExpectedOutputFiles) {
19251
19291
  expectedOutputFiles = newExpectedOutputFiles;
19252
19292
  }
@@ -19265,8 +19305,10 @@ var Runtime = {
19265
19305
  getObjectTemplate,
19266
19306
  getExporterModuleTemplate,
19267
19307
  getTypesFileTemplate,
19308
+ getEnumTemplate,
19268
19309
  getExpectedOutputFiles,
19269
- compileTemplates
19310
+ compileTemplates,
19311
+ getOneOfTemplate
19270
19312
  };
19271
19313
 
19272
19314
  function getSourceFileDirectory() {
@@ -19406,13 +19448,20 @@ function toPascalCase(input) {
19406
19448
  .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
19407
19449
  .join('');
19408
19450
  }
19451
+ function toPascalCaseHelper(input) {
19452
+ const inputString = decodeString(input);
19453
+ if (inputString === null) {
19454
+ return input;
19455
+ }
19456
+ return toPascalCase(inputString);
19457
+ }
19409
19458
  function registerTemplateHelpers() {
19410
19459
  Handlebars.registerHelper('getOptionalKeys', getOptionalKeys);
19411
19460
  Handlebars.registerHelper('getRequiredKeys', getRequiredKeys);
19412
19461
  Handlebars.registerHelper('areRequiredKeysPresent', (object) => getRequiredKeys(object).length > 0);
19413
19462
  Handlebars.registerHelper('getReferencedTypes', getReferencedTypes);
19414
19463
  Handlebars.registerHelper('getReferencedTypeModules', getReferencedTypeModules);
19415
- Handlebars.registerHelper('toPascalCase', toPascalCase);
19464
+ Handlebars.registerHelper('toPascalCase', toPascalCaseHelper);
19416
19465
  Handlebars.registerHelper('isNonEmptyArray', (value) => Array.isArray(value) && value.length === 0);
19417
19466
  Handlebars.registerHelper('eq', (value1, value2) => value1 === value2);
19418
19467
  }
@@ -19494,49 +19543,94 @@ function resolveAndGetReferenceName(reference) {
19494
19543
  return getReferenceName(reference);
19495
19544
  }
19496
19545
  function getLanguageDataType(dataType, format, items) {
19546
+ const result = {
19547
+ dataType,
19548
+ references: new Set(),
19549
+ primitives: new Set()
19550
+ };
19497
19551
  const typeMapper = Runtime.getConfig().language.typeMapper ?? null;
19498
19552
  const mappedType = typeMapper !== null ? typeMapper[dataType] : null;
19553
+ const itemReference =
19554
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
19555
+ items !== null && items.$ref !== null ? resolveAndGetReferenceName(items.$ref) : null;
19499
19556
  const itemsType =
19500
19557
  // eslint-disable-next-line
19501
19558
  items !== null
19502
19559
  ? items.type !== null
19503
19560
  ? getLanguageDataType(items.type, items.format, items.items)
19504
- : items.$ref !== null
19505
- ? resolveAndGetReferenceName(items.$ref)
19561
+ : itemReference !== null
19562
+ ? {
19563
+ dataType: itemReference,
19564
+ references: new Set([itemReference]),
19565
+ primitives: new Set()
19566
+ }
19506
19567
  : null
19507
19568
  : null;
19508
19569
  const fillerPatterns = [];
19509
19570
  if (itemsType !== null) {
19510
- fillerPatterns.push({ regex: /~ItemType~/g, value: itemsType });
19571
+ fillerPatterns.push({ regex: /~ItemType~/g, value: itemsType.dataType });
19511
19572
  }
19573
+ let mappedTypeWithFormat = null;
19574
+ let defaultType = null;
19512
19575
  if (typeof mappedType === 'string') {
19513
- return fillPatterns(mappedType, fillerPatterns);
19576
+ result.dataType = fillPatterns(mappedType, fillerPatterns);
19514
19577
  }
19515
19578
  else if (isJSON(mappedType)) {
19516
- const defaultType = mappedType.default;
19517
- const mappedTypeWithFormat = mappedType[format ?? ''] ?? defaultType;
19579
+ defaultType = mappedType.default;
19580
+ mappedTypeWithFormat = mappedType[format ?? ''] ?? defaultType;
19518
19581
  if (typeof mappedTypeWithFormat === 'string') {
19519
- return fillPatterns(mappedTypeWithFormat, fillerPatterns);
19582
+ result.dataType = fillPatterns(mappedTypeWithFormat, fillerPatterns);
19520
19583
  }
19521
19584
  }
19522
- return dataType;
19585
+ /**
19586
+ * @todo: Segregate array & variable type generation
19587
+ */
19588
+ const primitiveElementType = items?.$ref !== null
19589
+ ? null
19590
+ : mappedTypeWithFormat === null
19591
+ ? itemsType !== null
19592
+ ? itemsType.dataType
19593
+ : result.dataType
19594
+ : typeof mappedType === 'string' && items?.$ref !== null
19595
+ ? mappedType
19596
+ : null;
19597
+ if (itemsType !== null && primitiveElementType !== null) {
19598
+ result.itemType = primitiveElementType;
19599
+ }
19600
+ else if (itemsType !== null && itemReference !== null) {
19601
+ result.itemType = itemReference;
19602
+ }
19603
+ if (itemsType !== null) {
19604
+ result.references = new Set([...result.references, ...itemsType.references]);
19605
+ result.primitives =
19606
+ primitiveElementType !== null
19607
+ ? new Set([...result.primitives, primitiveElementType])
19608
+ : result.primitives;
19609
+ }
19610
+ return result;
19523
19611
  }
19524
- function generateType(typeName, typeInfo, groupedTypes = false) {
19525
- const result = {
19526
- content: '',
19527
- references: new Set(),
19528
- primitives: new Set()
19529
- };
19612
+ function generateObjectType(typeName, typeInfo) {
19530
19613
  const templateInput = {
19531
19614
  typeName,
19615
+ description: typeInfo.description,
19616
+ example: typeInfo.example,
19532
19617
  properties: {}
19533
19618
  };
19619
+ const result = {
19620
+ content: '',
19621
+ references: new Set(),
19622
+ primitives: new Set(),
19623
+ templateInput
19624
+ };
19534
19625
  let recursiveTypeGenOutput = null;
19626
+ let dynamicGeneratedType = '';
19535
19627
  for (const propertyName in typeInfo.properties) {
19536
- const propertyType = typeInfo.properties[propertyName].type;
19537
- const propertyFormat = typeInfo.properties[propertyName].format;
19538
- const propertyItems = typeInfo.properties[propertyName].items ?? null;
19539
- const reference = typeInfo.properties[propertyName].$ref ?? null;
19628
+ const propertyDetails = typeInfo.properties[propertyName];
19629
+ const propertyType = propertyDetails.type;
19630
+ const propertyFormat = propertyDetails.format;
19631
+ const propertyItems = propertyDetails.items ?? null;
19632
+ const reference = propertyDetails.$ref ?? null;
19633
+ const enumValues = propertyDetails.enum ?? null;
19540
19634
  // Throwing error in case neither property type nor reference to a different type is present
19541
19635
  if (propertyType === null && reference === null) {
19542
19636
  throw new InvalidSpecFileError('Invalid property type for: ' + typeName + '.' + propertyName);
@@ -19553,9 +19647,14 @@ function generateType(typeName, typeInfo, groupedTypes = false) {
19553
19647
  isReferenced = true;
19554
19648
  result.references.add(recursivePropertyName);
19555
19649
  }
19650
+ else if (enumValues !== null) {
19651
+ const enumName = toPascalCase(propertyName) + 'Enum';
19652
+ dynamicGeneratedType = generateEnumType(enumName, propertyDetails).content;
19653
+ languageDataType = enumName;
19654
+ }
19556
19655
  else if (propertyType === 'object') {
19557
19656
  recursivePropertyName = toPascalCase(propertyName);
19558
- recursiveTypeGenOutput = generateType(recursivePropertyName, typeInfo.properties[propertyName], groupedTypes);
19657
+ recursiveTypeGenOutput = generateObjectType(recursivePropertyName, typeInfo.properties[propertyName]);
19559
19658
  languageDataType = recursivePropertyName;
19560
19659
  for (const reference of recursiveTypeGenOutput.references.values()) {
19561
19660
  result.references.add(reference);
@@ -19565,7 +19664,7 @@ function generateType(typeName, typeInfo, groupedTypes = false) {
19565
19664
  }
19566
19665
  }
19567
19666
  else if (propertyType !== null) {
19568
- languageDataType = getLanguageDataType(propertyType, propertyFormat, propertyItems);
19667
+ languageDataType = getLanguageDataType(propertyType, propertyFormat, propertyItems).dataType;
19569
19668
  result.primitives.add(propertyItems !== null ? 'Array' : languageDataType);
19570
19669
  if (propertyItems !== null) {
19571
19670
  const itemsType = propertyItems.type ?? getReferenceName(propertyItems.$ref ?? '');
@@ -19583,20 +19682,129 @@ function generateType(typeName, typeInfo, groupedTypes = false) {
19583
19682
  required: typeInfo.required?.includes(propertyName) ?? false,
19584
19683
  referenced: isReferenced,
19585
19684
  primitiveType,
19586
- composerType
19685
+ composerType,
19686
+ example: propertyDetails.example,
19687
+ description: propertyDetails.description
19587
19688
  }
19588
19689
  };
19589
19690
  }
19590
19691
  result.content =
19591
- Runtime.getObjectTemplate()(templateInput) + (recursiveTypeGenOutput?.content ?? '');
19692
+ Runtime.getObjectTemplate()(templateInput) +
19693
+ (recursiveTypeGenOutput?.content ?? '') +
19694
+ dynamicGeneratedType;
19592
19695
  return result;
19593
19696
  }
19594
- function generateTypes(types, groupedTypes = false) {
19697
+ function generateEnumType(typeName, typeInfo) {
19698
+ if (typeInfo.enum === null || typeInfo.enum.length === 0 || typeInfo.type === null) {
19699
+ throw new InvalidSpecFileError('Invalid enum type for: ' + typeName);
19700
+ }
19701
+ const templateInput = {
19702
+ typeName,
19703
+ enumType: typeInfo.type,
19704
+ values: typeInfo.enum,
19705
+ example: typeInfo.example,
19706
+ description: typeInfo.description
19707
+ };
19708
+ const result = {
19709
+ content: '',
19710
+ references: new Set(),
19711
+ primitives: new Set(),
19712
+ templateInput
19713
+ };
19714
+ result.content = Runtime.getEnumTemplate()(templateInput);
19715
+ return result;
19716
+ }
19717
+ function generateOneOfTypes(typeName, typeInfo) {
19718
+ const result = {
19719
+ content: '',
19720
+ references: new Set(),
19721
+ primitives: new Set()
19722
+ };
19723
+ if (typeInfo.oneOf === null || typeInfo.oneOf.length === 0) {
19724
+ throw new InvalidSpecFileError('Invalid oneOf type for: ' + typeName);
19725
+ }
19726
+ const templateInput = {
19727
+ typeName,
19728
+ compositions: []
19729
+ };
19730
+ for (let index = 0; index < typeInfo.oneOf.length; index++) {
19731
+ const oneOfItem = typeInfo.oneOf[index];
19732
+ if (oneOfItem.$ref !== null) {
19733
+ const referenceName = resolveAndGetReferenceName(oneOfItem.$ref);
19734
+ const composition = {
19735
+ source: 'referenced',
19736
+ referencedType: referenceName
19737
+ };
19738
+ templateInput.compositions.push(composition);
19739
+ result.references.add(referenceName);
19740
+ }
19741
+ else {
19742
+ const generatedType = generateType(typeName + (index + 1), oneOfItem);
19743
+ if (generatedType === null) {
19744
+ throw new InvalidSpecFileError('Invalid oneOf type for: ' + typeName);
19745
+ }
19746
+ const composition = {
19747
+ dataType: oneOfItem.type,
19748
+ templateInput: generatedType.templateInput,
19749
+ source: 'inline',
19750
+ content: generatedType.content
19751
+ };
19752
+ templateInput.compositions.push(composition);
19753
+ for (const reference of generatedType.references.values()) {
19754
+ result.references.add(reference);
19755
+ }
19756
+ for (const primitive of generatedType.primitives.values()) {
19757
+ result.primitives.add(primitive);
19758
+ }
19759
+ }
19760
+ }
19761
+ result.content = Runtime.getOneOfTemplate()(templateInput);
19762
+ return result;
19763
+ }
19764
+ function generateVariableType(typeName, typeInfo) {
19765
+ if (typeInfo.type === null) {
19766
+ return null;
19767
+ }
19768
+ const dataType = getLanguageDataType(typeInfo.type, typeInfo.format, typeInfo.items);
19769
+ const _primitives = [...dataType.primitives];
19770
+ if (typeInfo.type === 'array' && dataType.references.size !== 0) {
19771
+ _primitives.push('Array');
19772
+ }
19773
+ else if (typeInfo.type !== 'array' && typeInfo.$ref === null) {
19774
+ _primitives.push(dataType.dataType);
19775
+ }
19776
+ return {
19777
+ content: '',
19778
+ references: dataType.references,
19779
+ primitives: new Set(_primitives),
19780
+ templateInput: {
19781
+ typeName,
19782
+ dataType: dataType.dataType,
19783
+ itemType: dataType.itemType,
19784
+ primitiveType: typeInfo.type
19785
+ }
19786
+ };
19787
+ }
19788
+ function generateType(typeName, typeInfo) {
19789
+ if (typeInfo.type === 'object') {
19790
+ return generateObjectType(typeName, typeInfo);
19791
+ }
19792
+ if (typeInfo.enum !== null) {
19793
+ return generateEnumType(typeName, typeInfo);
19794
+ }
19795
+ if (typeInfo.oneOf !== null) {
19796
+ return generateOneOfTypes(typeName, typeInfo);
19797
+ }
19798
+ return generateVariableType(typeName, typeInfo);
19799
+ }
19800
+ function generateTypes(types) {
19595
19801
  const result = {};
19596
19802
  for (const type in types) {
19597
19803
  const typeInfo = types[type];
19598
19804
  const genType = generateType(type, typeInfo);
19599
- result[type] = genType;
19805
+ if (genType !== null) {
19806
+ result[type] = genType;
19807
+ }
19600
19808
  }
19601
19809
  return result;
19602
19810
  }
@@ -19612,7 +19820,7 @@ function generator(specFileData) {
19612
19820
  // generating grouped types
19613
19821
  const groupedTypes = {};
19614
19822
  for (const groupName in specFileData.groupedTypes) {
19615
- groupedTypes[groupName] = generateTypes(specFileData.groupedTypes[groupName], true);
19823
+ groupedTypes[groupName] = generateTypes(specFileData.groupedTypes[groupName]);
19616
19824
  }
19617
19825
  result.groupedTypes = groupedTypes;
19618
19826
  return result;
@@ -19762,6 +19970,8 @@ async function config$1(inputFilePath, outputDirectory, typesWriterMode, grouped
19762
19970
  const objectSyntax = await readFile(directoryPrefix + 'templates/typescript/object-syntax.hbs', devMode);
19763
19971
  const exporterModuleSyntax = await readFile(directoryPrefix + 'templates/typescript/exporter-module-syntax.hbs', devMode);
19764
19972
  const typesFileSyntax = await readFile(directoryPrefix + 'templates/typescript/types-file-syntax.hbs', devMode);
19973
+ const enumSyntax = await readFile(directoryPrefix + 'templates/typescript/enum-syntax.hbs', devMode);
19974
+ const oneOfSyntax = await readFile(directoryPrefix + 'templates/typescript/oneOf-syntax.hbs', devMode);
19765
19975
  const config = {
19766
19976
  input: inputFilePath,
19767
19977
  output: {
@@ -19776,7 +19986,9 @@ async function config$1(inputFilePath, outputDirectory, typesWriterMode, grouped
19776
19986
  template: {
19777
19987
  objectSyntax,
19778
19988
  exporterModuleSyntax,
19779
- typesFileSyntax
19989
+ typesFileSyntax,
19990
+ enumSyntax,
19991
+ oneOfSyntax
19780
19992
  },
19781
19993
  language: {
19782
19994
  exporterModuleName: 'index',
@@ -19800,6 +20012,8 @@ async function config(inputFilePath, outputDirectory, typesWriterMode, groupedTy
19800
20012
  const objectSyntax = await readFile(directoryPrefix + 'templates/typescript-with-decoders/object-syntax.hbs', devMode);
19801
20013
  const exporterModuleSyntax = await readFile(directoryPrefix + 'templates/typescript/exporter-module-syntax.hbs', devMode);
19802
20014
  const typesFileSyntax = await readFile(directoryPrefix + 'templates/typescript-with-decoders/types-file-syntax.hbs', devMode);
20015
+ const enumSyntax = await readFile(directoryPrefix + 'templates/typescript-with-decoders/enum-syntax.hbs', devMode);
20016
+ const oneOfSyntax = await readFile(directoryPrefix + 'templates/typescript-with-decoders/oneOf-syntax.hbs', devMode);
19803
20017
  const config = {
19804
20018
  input: inputFilePath,
19805
20019
  output: {
@@ -19814,7 +20028,9 @@ async function config(inputFilePath, outputDirectory, typesWriterMode, groupedTy
19814
20028
  template: {
19815
20029
  objectSyntax,
19816
20030
  exporterModuleSyntax,
19817
- typesFileSyntax
20031
+ typesFileSyntax,
20032
+ enumSyntax,
20033
+ oneOfSyntax
19818
20034
  },
19819
20035
  language: {
19820
20036
  exporterModuleName: 'index',
@@ -19879,7 +20095,7 @@ async function runner(language, inputFilePath, outputDirectory, _typesWriterMode
19879
20095
  }
19880
20096
  }
19881
20097
  greeting();
19882
- const program = new Command().version('0.2.1');
20098
+ const program = new Command().version('0.4.0');
19883
20099
  program
19884
20100
  .command('generate')
19885
20101
  .description('Generate types for your language from a type spec file')
package/dist/runtime.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Configuration, ExporterModuleTemplateInput, ObjectTemplateInput, SpecFileData, TypeFilePath, TypesFileTemplateInput } from '$types';
1
+ import type { Configuration, EnumTemplateInput, ExporterModuleTemplateInput, ObjectTemplateInput, OneOfTemplateInput, SpecFileData, TypeFilePath, TypesFileTemplateInput } from '$types';
2
2
  declare function setConfig(newConfig: Configuration): void;
3
3
  declare function getConfig(): Configuration;
4
4
  declare function setSpecFileData(newSpecFileData: SpecFileData): void;
@@ -7,6 +7,8 @@ declare function compileTemplates(): void;
7
7
  declare function getObjectTemplate(): HandlebarsTemplateDelegate<ObjectTemplateInput>;
8
8
  declare function getExporterModuleTemplate(): HandlebarsTemplateDelegate<ExporterModuleTemplateInput>;
9
9
  declare function getTypesFileTemplate(): HandlebarsTemplateDelegate<TypesFileTemplateInput>;
10
+ declare function getEnumTemplate(): HandlebarsTemplateDelegate<EnumTemplateInput>;
11
+ declare function getOneOfTemplate(): HandlebarsTemplateDelegate<OneOfTemplateInput>;
10
12
  declare function setExpectedOutputFiles(newExpectedOutputFiles: Map<string, TypeFilePath>): void;
11
13
  declare function getExpectedOutputFiles(): Map<string, TypeFilePath>;
12
14
  declare const _default: {
@@ -18,7 +20,9 @@ declare const _default: {
18
20
  getObjectTemplate: typeof getObjectTemplate;
19
21
  getExporterModuleTemplate: typeof getExporterModuleTemplate;
20
22
  getTypesFileTemplate: typeof getTypesFileTemplate;
23
+ getEnumTemplate: typeof getEnumTemplate;
21
24
  getExpectedOutputFiles: typeof getExpectedOutputFiles;
22
25
  compileTemplates: typeof compileTemplates;
26
+ getOneOfTemplate: typeof getOneOfTemplate;
23
27
  };
24
28
  export default _default;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @type { {{typeName}} }
3
+ {{#if description}}
4
+ * @description {{{description}}}
5
+ {{/if}}
6
+ {{#if example}}
7
+ * @example {{{example}}}
8
+ {{/if}}
9
+ */
10
+ export type {{typeName}} =
11
+ {{#each values}}
12
+ | {{#if (eq ../enumType 'string') }}'{{/if}}{{{this}}}{{#if (eq ../enumType 'string')}}'{{/if}}
13
+ {{/each}};
@@ -1,5 +1,24 @@
1
+ /**
2
+ * @type { {{typeName}} }
3
+ {{#if description}}
4
+ * @description {{{description}}}
5
+ {{/if}}
6
+ {{#if example}}
7
+ * @example {{{example}}}
8
+ {{/if}}
9
+ */
1
10
  export type {{typeName}} = {
2
11
  {{#each properties}}
12
+ /**
13
+ {{#if this.description}}
14
+ * @description {{{this.description}}}
15
+ {{/if}}
16
+ * @type { {{this.type}} }
17
+ * @memberof {{../typeName}}
18
+ {{#if this.example}}
19
+ * @example {{{this.example}}}
20
+ {{/if}}
21
+ */
3
22
  {{@key}}: {{{this.type}}}{{#unless this.required}} | null{{/unless}};
4
23
  {{/each}}
5
24
  };
@@ -0,0 +1,19 @@
1
+ export type {{typeName}} =
2
+ {{#each compositions}}
3
+ | {{#if (eq this.source 'referenced')}}{{referencedType}}
4
+ {{else if (eq this.source 'inline')}}
5
+ {{#if this.templateInput.values}}
6
+ {{#each this.templateInput.values}}
7
+ {{#unless @first}}|{{/unless}} {{#if (eq ../this.templateInput.enumType 'string') }}'{{/if}}{{{this}}}{{#if (eq ../this.templateInput/enumType 'string')}}'{{/if}}
8
+ {{/each}}
9
+ {{else if (eq this.dataType 'object')}}
10
+ {
11
+ {{#each this.templateInput.properties}}
12
+ {{@key}}: {{{this.type}}}{{#unless this.required}} | null{{/unless}};
13
+ {{/each}}
14
+ }
15
+ {{else}}
16
+ {{this.templateInput.dataType}}
17
+ {{/if}}
18
+ {{/if}}
19
+ {{/each}};
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @type { {{typeName}} }
3
+ {{#if description}}
4
+ * @description {{{description}}}
5
+ {{/if}}
6
+ {{#if example}}
7
+ * @example {{{example}}}
8
+ {{/if}}
9
+ */
10
+ export type {{typeName}} =
11
+ {{#each values}}
12
+ | {{#if (eq ../enumType 'string') }}'{{/if}}{{{this}}}{{#if (eq ../enumType 'string')}}'{{/if}}
13
+ {{/each}};
14
+
15
+ export function decode{{typeName}}(rawInput: unknown): {{typeName}} | null {
16
+ switch (rawInput) {
17
+ {{#each values}}
18
+ case {{#if (eq ../enumType 'string') }}'{{/if}}{{this}}{{#if (eq ../enumType 'string')}}'{{/if}}:
19
+ {{/each}}
20
+ return rawInput;
21
+ }
22
+ return null;
23
+ }
@@ -1,5 +1,24 @@
1
+ /**
2
+ * @type { {{typeName}} }
3
+ {{#if description}}
4
+ * @description {{{description}}}
5
+ {{/if}}
6
+ {{#if example}}
7
+ * @example {{{example}}}
8
+ {{/if}}
9
+ */
1
10
  export type {{typeName}} = {
2
11
  {{#each properties}}
12
+ /**
13
+ {{#if this.description}}
14
+ * @description {{{this.description}}}
15
+ {{/if}}
16
+ * @type { {{this.type}} }
17
+ * @memberof {{../typeName}}
18
+ {{#if this.example}}
19
+ * @example {{{this.example}}}
20
+ {{/if}}
21
+ */
3
22
  {{@key}}: {{{this.type}}}{{#unless this.required}} | null{{/unless}};
4
23
  {{/each}}
5
24
  };
@@ -0,0 +1,74 @@
1
+ export type {{typeName}} =
2
+ {{#each compositions}}
3
+ | {{#if (eq this.source 'referenced')}}C{{referencedType}}
4
+ {{else if (eq this.source 'inline')}}
5
+ {{#if this.templateInput.values}}
6
+ {{this.templateInput.typeName}}
7
+ {{else if (eq this.dataType 'object')}}
8
+ C{{this.templateInput.typeName}}
9
+ {{else}}
10
+ {{this.templateInput.dataType}}
11
+ {{/if}}
12
+ {{/if}}
13
+ {{/each}};
14
+
15
+ export function decode{{typeName}}(rawInput: unknown): {{typeName}} | null {
16
+ const result: {{typeName}} | null =
17
+ {{#each compositions}}
18
+ {{#if (eq this.source 'referenced')}}
19
+ decodeC{{referencedType}}(rawInput)
20
+ {{else if (eq this.dataType 'object')}}
21
+ decodeC{{this.templateInput.typeName}}(rawInput)
22
+ {{else if (eq this.templateInput.primitiveType 'array')}}
23
+ decodeArray(rawInput, decode{{{toPascalCase this.templateInput.itemType}}})
24
+ {{else if this.templateInput.values}}
25
+ decode{{this.templateInput.typeName}}(rawInput)
26
+ {{else}}
27
+ decode{{{toPascalCase this.templateInput.dataType}}}(rawInput)
28
+ {{/if}}{{#unless @last}}??{{/unless}}
29
+ {{/each}};
30
+ return result;
31
+ }
32
+
33
+
34
+ {{#each compositions}}
35
+
36
+ {{#if this.templateInput.values}}
37
+ {{{this.content}}}
38
+ {{else if (eq this.source 'referenced')}}
39
+ export class C{{referencedType}} {
40
+ data: {{referencedType}};
41
+ constructor(data: {{referencedType}}) {
42
+ this.data = data;
43
+ }
44
+ }
45
+
46
+ export function decodeC{{referencedType}}(rawInput: unknown): C{{referencedType}} | null {
47
+ const result = decode{{referencedType}}(rawInput);
48
+ if (result === null) {
49
+ return null;
50
+ }
51
+ return new C{{referencedType}}(result);
52
+ }
53
+
54
+ {{else if (eq this.dataType 'object')}}
55
+
56
+ {{{this.content}}}
57
+
58
+ export class C{{this.templateInput.typeName}} {
59
+ data: {{this.templateInput.typeName}};
60
+ constructor(data: {{this.templateInput.typeName}}) {
61
+ this.data = data;
62
+ }
63
+ }
64
+
65
+ export function decodeC{{this.templateInput.typeName}}(rawInput: unknown) {
66
+ const result = decode{{this.templateInput.typeName}}(rawInput);
67
+ if (result === null) {
68
+ return null;
69
+ }
70
+ return new C{{this.templateInput.typeName}}(result);
71
+ }
72
+
73
+ {{/if}}
74
+ {{/each}}
@@ -1,5 +1,6 @@
1
- import type { GroupedTypesWriterMode, ObjectTemplateInputProperties, SpecFileData, TypesWriterMode } from '.';
1
+ import type { EnumTemplateInput, GroupedTypesWriterMode, ObjectTemplateInputProperties, SpecFileData, TypesWriterMode } 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 decodeObjectTemplateInputProperties(rawInput: unknown): ObjectTemplateInputProperties | null;
6
+ export declare function decodeEnumTemplateInput(rawInput: unknown): EnumTemplateInput | null;
@@ -20,6 +20,8 @@ export type Template = {
20
20
  objectSyntax: string;
21
21
  exporterModuleSyntax: string;
22
22
  typesFileSyntax: string;
23
+ enumSyntax: string;
24
+ oneOfSyntax: string;
23
25
  };
24
26
  export type LanguageConfig = {
25
27
  exporterModuleName: string;
@@ -54,12 +56,18 @@ export type TypeInfo = {
54
56
  items: TypeInfo | null;
55
57
  properties: TypeProperties | null;
56
58
  $ref: string | null;
59
+ oneOf: TypeInfo[] | null;
60
+ enum: string[] | number[] | null;
61
+ description: string | null;
62
+ example: string | number | null;
57
63
  };
58
64
  type PropertyName = string;
59
65
  export type TypeProperties = Record<PropertyName, TypeInfo>;
60
66
  export type TypeDataType = 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'unknown';
61
67
  export type ObjectTemplateInput = {
62
68
  typeName: string;
69
+ example: string | number | null;
70
+ description: string | null;
63
71
  properties: ObjectTemplateInputProperties;
64
72
  };
65
73
  export type ObjectTemplateInputProperties = Record<PropertyName, ObjectTemplateInputProperty>;
@@ -69,6 +77,8 @@ export type ObjectTemplateInputProperty = {
69
77
  referenced: boolean;
70
78
  primitiveType: string;
71
79
  composerType: string | null;
80
+ example: string | number | null;
81
+ description: string | null;
72
82
  };
73
83
  export type ExporterModuleTemplateInput = {
74
84
  modules: string[];
@@ -84,6 +94,31 @@ export type ReferencedModule = {
84
94
  moduleRelativePath: string;
85
95
  referencedTypes: string[];
86
96
  };
97
+ export type EnumTemplateInput = {
98
+ typeName: string;
99
+ enumType: string;
100
+ values: string[] | number[];
101
+ example: string | number | null;
102
+ description: string | null;
103
+ };
104
+ export type OneOfTemplateInput = {
105
+ typeName: string;
106
+ compositions: OneOfTemplateInputComposition[];
107
+ };
108
+ export type OneOfTemplateInputComposition = {
109
+ dataType?: TypeDataType | null;
110
+ templateInput?: TemplateInput;
111
+ source: 'inline' | 'referenced';
112
+ referencedType?: string;
113
+ content?: string;
114
+ };
115
+ export type VariableTemplateInput = {
116
+ typeName: string;
117
+ dataType: string;
118
+ primitiveType: string;
119
+ itemType?: string;
120
+ };
121
+ export type TemplateInput = ObjectTemplateInput | EnumTemplateInput | VariableTemplateInput;
87
122
  export type GenerationResult = {
88
123
  groupedTypes: GroupedTypesOutput;
89
124
  types: GeneratedTypes;
@@ -92,6 +127,7 @@ export type GeneratedType = {
92
127
  content: string;
93
128
  references: Set<string>;
94
129
  primitives: Set<string>;
130
+ templateInput?: TemplateInput;
95
131
  };
96
132
  export type GroupedTypesOutput = Record<GroupName, GeneratedTypes>;
97
133
  export type GeneratedTypes = Record<TypeName, GeneratedType>;
@@ -7,6 +7,7 @@ export declare function getRequiredKeys(object: unknown): string[];
7
7
  export declare function getReferencedTypes(object: unknown): string[];
8
8
  export declare function getReferencedTypeModules(_referencedTypes: unknown, _writtenAt: string): unknown[];
9
9
  export declare function toPascalCase(input: string): string;
10
+ export declare function toPascalCaseHelper(input: unknown): string | unknown;
10
11
  export declare function registerTemplateHelpers(): void;
11
12
  export declare function readNestedValue(json: JSONObject, keyPath: string[]): JSONObject;
12
13
  export declare function generateRelativePath(fromPath: string, toPath: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-crafter",
3
- "version": "0.2.1",
3
+ "version": "0.4.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",