type-crafter 0.1.1 → 0.2.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
@@ -10858,11 +10858,15 @@ function decodeObjectTemplateInputProperty(rawInput) {
10858
10858
  const required = decodeBoolean(rawInput.required);
10859
10859
  const _type = decodeString(rawInput.type);
10860
10860
  const referenced = decodeBoolean(rawInput.referenced);
10861
- if (required !== null && _type !== null && referenced !== null) {
10861
+ const primitiveType = decodeString(rawInput.primitiveType);
10862
+ const composerType = decodeString(rawInput.composerType);
10863
+ if (required !== null && _type !== null && referenced !== null && primitiveType !== null) {
10862
10864
  return {
10863
10865
  type: _type,
10864
10866
  required,
10865
- referenced
10867
+ referenced,
10868
+ primitiveType,
10869
+ composerType
10866
10870
  };
10867
10871
  }
10868
10872
  }
@@ -19195,20 +19199,20 @@ function handleErrors(error) {
19195
19199
  }
19196
19200
  }
19197
19201
 
19198
- let config$1 = null;
19202
+ let config$2 = null;
19199
19203
  let specFileData = null;
19200
19204
  let objectSyntaxTemplate = null;
19201
19205
  let exporterModuleSyntaxTemplate = null;
19202
19206
  let typesFileSyntaxTemplate = null;
19203
19207
  let expectedOutputFiles = null;
19204
19208
  function setConfig(newConfig) {
19205
- config$1 = newConfig;
19209
+ config$2 = newConfig;
19206
19210
  }
19207
19211
  function getConfig() {
19208
- if (config$1 === null) {
19212
+ if (config$2 === null) {
19209
19213
  throw new RuntimeError('Failed to load configuration!');
19210
19214
  }
19211
- return config$1;
19215
+ return config$2;
19212
19216
  }
19213
19217
  function setSpecFileData(newSpecFileData) {
19214
19218
  specFileData = newSpecFileData;
@@ -19340,6 +19344,19 @@ function getOptionalKeys(object) {
19340
19344
  }
19341
19345
  return nullableKeys;
19342
19346
  }
19347
+ function getRequiredKeys(object) {
19348
+ const requiredKeys = [];
19349
+ const properties = decodeObjectTemplateInputProperties(object);
19350
+ if (properties !== null) {
19351
+ for (const propertyName in properties) {
19352
+ const property = properties[propertyName];
19353
+ if (property.required) {
19354
+ requiredKeys.push(propertyName);
19355
+ }
19356
+ }
19357
+ }
19358
+ return requiredKeys;
19359
+ }
19343
19360
  function getReferencedTypes(object) {
19344
19361
  const referencedTypes = [];
19345
19362
  const properties = decodeObjectTemplateInputProperties(object);
@@ -19391,8 +19408,13 @@ function toPascalCase(input) {
19391
19408
  }
19392
19409
  function registerTemplateHelpers() {
19393
19410
  Handlebars.registerHelper('getOptionalKeys', getOptionalKeys);
19411
+ Handlebars.registerHelper('getRequiredKeys', getRequiredKeys);
19412
+ Handlebars.registerHelper('areRequiredKeysPresent', (object) => getRequiredKeys(object).length > 0);
19394
19413
  Handlebars.registerHelper('getReferencedTypes', getReferencedTypes);
19395
19414
  Handlebars.registerHelper('getReferencedTypeModules', getReferencedTypeModules);
19415
+ Handlebars.registerHelper('toPascalCase', toPascalCase);
19416
+ Handlebars.registerHelper('isNonEmptyArray', (value) => Array.isArray(value) && value.length === 0);
19417
+ Handlebars.registerHelper('eq', (value1, value2) => value1 === value2);
19396
19418
  }
19397
19419
  function readNestedValue(json, keyPath) {
19398
19420
  let result = json;
@@ -19519,6 +19541,8 @@ function generateType(typeName, typeInfo, groupedTypes = false) {
19519
19541
  if (propertyType === null && reference === null) {
19520
19542
  throw new InvalidSpecFileError('Invalid property type for: ' + typeName + '.' + propertyName);
19521
19543
  }
19544
+ const primitiveType = propertyType ?? 'object';
19545
+ let composerType = null;
19522
19546
  let recursivePropertyName;
19523
19547
  let languageDataType = null;
19524
19548
  let isReferenced = false;
@@ -19542,7 +19566,12 @@ function generateType(typeName, typeInfo, groupedTypes = false) {
19542
19566
  }
19543
19567
  else if (propertyType !== null) {
19544
19568
  languageDataType = getLanguageDataType(propertyType, propertyFormat, propertyItems);
19545
- result.primitives.add(languageDataType);
19569
+ result.primitives.add(propertyItems !== null ? 'Array' : languageDataType);
19570
+ if (propertyItems !== null) {
19571
+ const itemsType = getReferenceName(propertyItems.$ref ?? '');
19572
+ result.references.add(itemsType);
19573
+ composerType = itemsType;
19574
+ }
19546
19575
  }
19547
19576
  if (languageDataType === null) {
19548
19577
  throw new InvalidSpecFileError(`Invalid language data type for: ${typeName}.${propertyName}`);
@@ -19552,7 +19581,9 @@ function generateType(typeName, typeInfo, groupedTypes = false) {
19552
19581
  [propertyName]: {
19553
19582
  type: languageDataType,
19554
19583
  required: typeInfo.required?.includes(propertyName) ?? false,
19555
- referenced: isReferenced
19584
+ referenced: isReferenced,
19585
+ primitiveType,
19586
+ composerType
19556
19587
  }
19557
19588
  };
19558
19589
  }
@@ -19724,12 +19755,51 @@ async function writeOutput(generationResult) {
19724
19755
  });
19725
19756
  }
19726
19757
 
19727
- async function config(inputFilePath, outputDirectory, typesWriterMode, groupedTypesWriterMode) {
19758
+ async function config$1(inputFilePath, outputDirectory, typesWriterMode, groupedTypesWriterMode) {
19759
+ const devMode = 'PRODUCTION'.includes('DEVELOPMENT');
19728
19760
  // PRODUCTION will be replaced with PRODUCTION when package is built.
19729
- const directoryPrefix = 'PRODUCTION'.includes('DEVELOPMENT') ? 'src/' : './';
19730
- const objectSyntax = await readFile(directoryPrefix + 'templates/typescript/object-syntax.hbs', false);
19731
- const exporterModuleSyntax = await readFile(directoryPrefix + 'templates/typescript/exporter-module-syntax.hbs', false);
19732
- const typesFileSyntax = await readFile(directoryPrefix + 'templates/typescript/types-file-syntax.hbs', false);
19761
+ const directoryPrefix = devMode ? 'src/' : './';
19762
+ const objectSyntax = await readFile(directoryPrefix + 'templates/typescript/object-syntax.hbs', devMode);
19763
+ const exporterModuleSyntax = await readFile(directoryPrefix + 'templates/typescript/exporter-module-syntax.hbs', devMode);
19764
+ const typesFileSyntax = await readFile(directoryPrefix + 'templates/typescript/types-file-syntax.hbs', devMode);
19765
+ const config = {
19766
+ input: inputFilePath,
19767
+ output: {
19768
+ cleanWrite: true,
19769
+ fileExtension: '.ts',
19770
+ directory: outputDirectory,
19771
+ writerMode: {
19772
+ groupedTypes: groupedTypesWriterMode,
19773
+ types: typesWriterMode
19774
+ }
19775
+ },
19776
+ template: {
19777
+ objectSyntax,
19778
+ exporterModuleSyntax,
19779
+ typesFileSyntax
19780
+ },
19781
+ language: {
19782
+ exporterModuleName: 'index',
19783
+ typeMapper: {
19784
+ string: { default: 'string', date: 'Date' },
19785
+ number: { default: 'number' },
19786
+ integer: { default: 'integer' },
19787
+ boolean: 'boolean',
19788
+ array: '~ItemType~[]',
19789
+ object: 'type',
19790
+ unknown: 'unknown'
19791
+ }
19792
+ }
19793
+ };
19794
+ return config;
19795
+ }
19796
+
19797
+ async function config(inputFilePath, outputDirectory, typesWriterMode, groupedTypesWriterMode) {
19798
+ const devMode = 'PRODUCTION'.includes('DEVELOPMENT');
19799
+ const directoryPrefix = devMode ? 'src/' : './';
19800
+ const objectSyntax = await readFile(directoryPrefix + 'templates/typescript-with-decoders/object-syntax.hbs', devMode);
19801
+ const exporterModuleSyntax = await readFile(directoryPrefix + 'templates/typescript/exporter-module-syntax.hbs', devMode);
19802
+ const typesFileSyntax = await readFile(directoryPrefix + 'templates/typescript-with-decoders/types-file-syntax.hbs', devMode);
19733
19803
  const config = {
19734
19804
  input: inputFilePath,
19735
19805
  output: {
@@ -19790,6 +19860,9 @@ async function runner(language, inputFilePath, outputDirectory, _typesWriterMode
19790
19860
  let generatorConfig = null;
19791
19861
  switch (language.toLowerCase()) {
19792
19862
  case 'typescript':
19863
+ generatorConfig = await config$1(inputFilePath, outputDirectory, typesWriterMode, groupedTypesWriterMode);
19864
+ break;
19865
+ case 'typescript-with-decoders':
19793
19866
  generatorConfig = await config(inputFilePath, outputDirectory, typesWriterMode, groupedTypesWriterMode);
19794
19867
  break;
19795
19868
  default:
@@ -19806,7 +19879,7 @@ async function runner(language, inputFilePath, outputDirectory, _typesWriterMode
19806
19879
  }
19807
19880
  }
19808
19881
  greeting();
19809
- const program = new Command().version('0.1.1');
19882
+ const program = new Command().version('0.2.0');
19810
19883
  program
19811
19884
  .command('generate')
19812
19885
  .description('Generate types for your language from a type spec file')
@@ -1 +1,2 @@
1
1
  export * as typescript from './typescript';
2
+ export * as typescriptWithDecoders from './typescript-with-decoders';
@@ -0,0 +1,2 @@
1
+ import type { Configuration, GroupedTypesWriterMode, TypesWriterMode } from '$types';
2
+ export declare function config(inputFilePath: string, outputDirectory: string, typesWriterMode: TypesWriterMode, groupedTypesWriterMode: GroupedTypesWriterMode): Promise<Configuration>;
@@ -0,0 +1,30 @@
1
+ export type {{typeName}} = {
2
+ {{#each properties}}
3
+ {{@key}}: {{{this.type}}}{{#unless this.required}} | null{{/unless}};
4
+ {{/each}}
5
+ };
6
+
7
+ export function decode{{typeName}}(rawInput: unknown): {{typeName}} | null {
8
+ if (isJSON(rawInput)) {
9
+ {{#each properties}}
10
+ const {{@key}} = {{#if (eq this.primitiveType 'array') }} decodeArray(rawInput.{{@key}}, decode{{{toPascalCase this.composerType}}}){{else}} decode{{{toPascalCase this.type}}}(rawInput.{{@key}}){{/if}};
11
+ {{/each}}
12
+
13
+ {{#if (areRequiredKeysPresent properties)}}
14
+ if (
15
+ {{#each (getRequiredKeys properties)}}
16
+ {{this}} === null{{#unless @last}} ||{{/unless}}
17
+ {{/each}}
18
+ ) {
19
+ return null;
20
+ }
21
+ {{/if}}
22
+
23
+ return {
24
+ {{#each properties}}
25
+ {{@key}},
26
+ {{/each}}
27
+ };
28
+ }
29
+ return null;
30
+ }
@@ -0,0 +1,7 @@
1
+ {{#each (getReferencedTypeModules referencedTypes writtenAt)}}
2
+ import { {{#each this.referencedTypes}}type {{this}}, decode{{this}}{{#unless @last}}, {{/unless}} {{/each}} } from '{{this.moduleRelativePath}}';
3
+ {{/each}}
4
+ import { isJSON, {{#each primitives}}decode{{{toPascalCase this}}}{{#unless @last}}, {{/unless}}{{/each}} } from 'type-decoder';
5
+
6
+ {{{typesContent}}}
7
+
@@ -67,6 +67,8 @@ export type ObjectTemplateInputProperty = {
67
67
  type: string;
68
68
  required: boolean;
69
69
  referenced: boolean;
70
+ primitiveType: string;
71
+ composerType: string | null;
70
72
  };
71
73
  export type ExporterModuleTemplateInput = {
72
74
  modules: string[];
@@ -3,6 +3,7 @@ export * from './file-system';
3
3
  export * from './logger';
4
4
  export declare function addValuesToMappedSet(map: Map<string, Set<string>>, key: string, values: string[]): void;
5
5
  export declare function getOptionalKeys(object: unknown): string[];
6
+ export declare function getRequiredKeys(object: unknown): string[];
6
7
  export declare function getReferencedTypes(object: unknown): string[];
7
8
  export declare function getReferencedTypeModules(_referencedTypes: unknown, _writtenAt: string): unknown[];
8
9
  export declare function toPascalCase(input: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "type-crafter",
3
- "version": "0.1.1",
3
+ "version": "0.2.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",