@twin.org/ts-to-openapi 0.0.1-next.9 → 0.0.1

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/bin/index.js CHANGED
File without changes
@@ -659,8 +659,13 @@ async function finaliseOutput(usedCommonResponseTypes, schemas, openApi, securit
659
659
  }
660
660
  }
661
661
  }
662
- if (finalSchemas.HttpStatusCode) {
663
- delete finalSchemas.HttpStatusCode;
662
+ // Remove standard types that we don't want in the final output
663
+ const removeTypes = ["HttpStatusCode", "Uint8Array", "ArrayBuffer"];
664
+ for (const type of removeTypes) {
665
+ delete finalSchemas[type];
666
+ }
667
+ for (const type in finalSchemas) {
668
+ processArrays(finalSchemas[type]);
664
669
  }
665
670
  const schemaKeys = Object.keys(finalSchemas);
666
671
  schemaKeys.sort();
@@ -672,7 +677,7 @@ async function finaliseOutput(usedCommonResponseTypes, schemas, openApi, securit
672
677
  schemas: sortedSchemas,
673
678
  securitySchemes
674
679
  };
675
- let json = JSON.stringify(openApi, undefined, " ");
680
+ let json = JSON.stringify(openApi, undefined, "\t");
676
681
  // Remove the reference only schemas, repeating until no more substitutions
677
682
  let performedSubstitution;
678
683
  do {
@@ -693,10 +698,7 @@ async function finaliseOutput(usedCommonResponseTypes, schemas, openApi, securit
693
698
  // Remove the array [] from the type names
694
699
  // eslint-disable-next-line unicorn/better-regex
695
700
  json = json.replace(/#\/components\/schemas\/(.*)\[\]/g, "#/components/schemas/ListOf$1");
696
- // Remove the partial markers
697
- json = json.replace(/Partial%3CI(.*?)%3E/g, "$1");
698
- // Cleanup the generic markers
699
- json = json.replace(/%3Cunknown%3E/g, "");
701
+ json = normaliseTypeName(json);
700
702
  // Remove external references
701
703
  for (const finalExternal in finalExternals) {
702
704
  json = json.replace(new RegExp(`"#/components/schemas/${core.StringHelper.stripPrefix(finalExternal)}"`, "g"), `"${finalExternals[finalExternal]}"`);
@@ -706,7 +708,7 @@ async function finaliseOutput(usedCommonResponseTypes, schemas, openApi, securit
706
708
  await promises.mkdir(path.dirname(outputFile), { recursive: true });
707
709
  }
708
710
  catch { }
709
- await promises.writeFile(outputFile, json);
711
+ await promises.writeFile(outputFile, `${json}\n`);
710
712
  }
711
713
  /**
712
714
  * Build the security schemas from the config.
@@ -850,10 +852,7 @@ async function generateSchemas(modelDirWildcards, types, outputWorkingDir) {
850
852
  const schema = generator.createSchema("*");
851
853
  if (schema.definitions) {
852
854
  for (const def in schema.definitions) {
853
- // Remove the partial markers
854
- let defSub = def.replace(/^Partial<(.*?)>/g, "$1");
855
- // Cleanup the generic markers
856
- defSub = defSub.replace(/</g, "%3C").replace(/>/g, "%3E");
855
+ const defSub = normaliseTypeName(def);
857
856
  allSchemas[defSub] = schema.definitions[def];
858
857
  }
859
858
  }
@@ -895,7 +894,7 @@ function extractTypes(allSchemas, requiredTypes, referencedSchemas) {
895
894
  function extractTypesFromSchema(allTypes, schema, output) {
896
895
  const additionalTypes = [];
897
896
  if (core.Is.stringValue(schema.$ref)) {
898
- additionalTypes.push(schema.$ref.replace("#/definitions/", "").replace(/^Partial%3C(.*?)%3E/g, "$1"));
897
+ additionalTypes.push(normaliseTypeName(schema.$ref).replace("#/definitions/", ""));
899
898
  }
900
899
  else if (core.Is.object(schema.items)) {
901
900
  if (core.Is.arrayValue(schema.items)) {
@@ -1088,6 +1087,79 @@ async function loadPackages(tsToOpenApiConfig, outputWorkingDir, typeRoots) {
1088
1087
  }
1089
1088
  return restRoutes;
1090
1089
  }
1090
+ /**
1091
+ * Process arrays in the schema object.
1092
+ * @param schemaObject The schema object to process.
1093
+ */
1094
+ function processArrays(schemaObject) {
1095
+ if (core.Is.object(schemaObject)) {
1096
+ // latest specs have singular items in `items` property
1097
+ // and multiple items in prefixItems, so update the schema accordingly
1098
+ // https://www.learnjsonschema.com/2020-12/applicator/items/
1099
+ // https://www.learnjsonschema.com/2020-12/applicator/prefixitems/
1100
+ const schemaItems = schemaObject.items;
1101
+ if (core.Is.array(schemaItems) || core.Is.object(schemaItems)) {
1102
+ schemaObject.prefixItems = core.ArrayHelper.fromObjectOrArray(schemaItems);
1103
+ delete schemaObject.items;
1104
+ }
1105
+ const additionalItems = schemaObject.additionalItems;
1106
+ if (core.Is.array(additionalItems) || core.Is.object(additionalItems)) {
1107
+ schemaObject.items = core.ArrayHelper.fromObjectOrArray(additionalItems)[0];
1108
+ delete schemaObject.additionalItems;
1109
+ }
1110
+ processSchemaDictionary(schemaObject.properties);
1111
+ processArrays(schemaObject.additionalProperties);
1112
+ processSchemaArray(schemaObject.allOf);
1113
+ processSchemaArray(schemaObject.anyOf);
1114
+ processSchemaArray(schemaObject.oneOf);
1115
+ }
1116
+ }
1117
+ /**
1118
+ * Process arrays in the schema object.
1119
+ * @param schemaDictionary The schema object to process.
1120
+ */
1121
+ function processSchemaDictionary(schemaDictionary) {
1122
+ if (core.Is.object(schemaDictionary)) {
1123
+ for (const item of Object.values(schemaDictionary)) {
1124
+ if (core.Is.object(item)) {
1125
+ processArrays(item);
1126
+ }
1127
+ }
1128
+ }
1129
+ }
1130
+ /**
1131
+ * Process arrays in the schema object.
1132
+ * @param schemaArray The schema object to process.
1133
+ */
1134
+ function processSchemaArray(schemaArray) {
1135
+ if (core.Is.arrayValue(schemaArray)) {
1136
+ for (const item of schemaArray) {
1137
+ if (core.Is.object(item)) {
1138
+ processArrays(item);
1139
+ }
1140
+ }
1141
+ }
1142
+ }
1143
+ /**
1144
+ * Cleanup TypeScript markers from the type name.
1145
+ * @param typeName The definition string to clean up.
1146
+ * @returns The cleaned up definition string.
1147
+ */
1148
+ function normaliseTypeName(typeName) {
1149
+ // Remove the partial markers
1150
+ let sTypeName = typeName.replace(/^Partial<(.*?)>/g, "$1");
1151
+ sTypeName = sTypeName.replace(/Partial%3CI(.*?)%3E/g, "$1");
1152
+ // Remove the omit markers
1153
+ sTypeName = sTypeName.replace(/^Omit<(.*?),.*>/g, "$1");
1154
+ sTypeName = sTypeName.replace(/Omit%3CI(.*?)%2C.*%3E/g, "$1");
1155
+ // Remove the pick markers
1156
+ sTypeName = sTypeName.replace(/^Pick<(.*?),.*>/g, "$1");
1157
+ sTypeName = sTypeName.replace(/Pick%3CI(.*?)%2C.*%3E/g, "$1");
1158
+ // Cleanup the generic markers
1159
+ sTypeName = sTypeName.replace(/</g, "%3C").replace(/>/g, "%3E");
1160
+ sTypeName = sTypeName.replace(/%3Cunknown%3E/g, "");
1161
+ return sTypeName;
1162
+ }
1091
1163
 
1092
1164
  // Copyright 2024 IOTA Stiftung.
1093
1165
  // SPDX-License-Identifier: Apache-2.0.
@@ -1107,7 +1179,7 @@ class CLI extends cliCore.CLIBase {
1107
1179
  return this.execute({
1108
1180
  title: "TWIN TypeScript To OpenAPI",
1109
1181
  appName: "ts-to-openapi",
1110
- version: "0.0.1-next.9",
1182
+ version: "0.0.1", // x-release-please-version
1111
1183
  icon: "⚙️ ",
1112
1184
  supportsEnvFiles: false,
1113
1185
  overrideOutputWidth: options?.overrideOutputWidth
@@ -2,7 +2,7 @@ import path from 'node:path';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { CLIDisplay, CLIUtils, CLIBase } from '@twin.org/cli-core';
4
4
  import { mkdir, rm, writeFile } from 'node:fs/promises';
5
- import { I18n, GeneralError, Is, StringHelper, ObjectHelper } from '@twin.org/core';
5
+ import { I18n, GeneralError, Is, StringHelper, ObjectHelper, ArrayHelper } from '@twin.org/core';
6
6
  import { HttpStatusCode, MimeTypes } from '@twin.org/web';
7
7
  import { createGenerator } from 'ts-json-schema-generator';
8
8
 
@@ -656,8 +656,13 @@ async function finaliseOutput(usedCommonResponseTypes, schemas, openApi, securit
656
656
  }
657
657
  }
658
658
  }
659
- if (finalSchemas.HttpStatusCode) {
660
- delete finalSchemas.HttpStatusCode;
659
+ // Remove standard types that we don't want in the final output
660
+ const removeTypes = ["HttpStatusCode", "Uint8Array", "ArrayBuffer"];
661
+ for (const type of removeTypes) {
662
+ delete finalSchemas[type];
663
+ }
664
+ for (const type in finalSchemas) {
665
+ processArrays(finalSchemas[type]);
661
666
  }
662
667
  const schemaKeys = Object.keys(finalSchemas);
663
668
  schemaKeys.sort();
@@ -669,7 +674,7 @@ async function finaliseOutput(usedCommonResponseTypes, schemas, openApi, securit
669
674
  schemas: sortedSchemas,
670
675
  securitySchemes
671
676
  };
672
- let json = JSON.stringify(openApi, undefined, " ");
677
+ let json = JSON.stringify(openApi, undefined, "\t");
673
678
  // Remove the reference only schemas, repeating until no more substitutions
674
679
  let performedSubstitution;
675
680
  do {
@@ -690,10 +695,7 @@ async function finaliseOutput(usedCommonResponseTypes, schemas, openApi, securit
690
695
  // Remove the array [] from the type names
691
696
  // eslint-disable-next-line unicorn/better-regex
692
697
  json = json.replace(/#\/components\/schemas\/(.*)\[\]/g, "#/components/schemas/ListOf$1");
693
- // Remove the partial markers
694
- json = json.replace(/Partial%3CI(.*?)%3E/g, "$1");
695
- // Cleanup the generic markers
696
- json = json.replace(/%3Cunknown%3E/g, "");
698
+ json = normaliseTypeName(json);
697
699
  // Remove external references
698
700
  for (const finalExternal in finalExternals) {
699
701
  json = json.replace(new RegExp(`"#/components/schemas/${StringHelper.stripPrefix(finalExternal)}"`, "g"), `"${finalExternals[finalExternal]}"`);
@@ -703,7 +705,7 @@ async function finaliseOutput(usedCommonResponseTypes, schemas, openApi, securit
703
705
  await mkdir(path.dirname(outputFile), { recursive: true });
704
706
  }
705
707
  catch { }
706
- await writeFile(outputFile, json);
708
+ await writeFile(outputFile, `${json}\n`);
707
709
  }
708
710
  /**
709
711
  * Build the security schemas from the config.
@@ -847,10 +849,7 @@ async function generateSchemas(modelDirWildcards, types, outputWorkingDir) {
847
849
  const schema = generator.createSchema("*");
848
850
  if (schema.definitions) {
849
851
  for (const def in schema.definitions) {
850
- // Remove the partial markers
851
- let defSub = def.replace(/^Partial<(.*?)>/g, "$1");
852
- // Cleanup the generic markers
853
- defSub = defSub.replace(/</g, "%3C").replace(/>/g, "%3E");
852
+ const defSub = normaliseTypeName(def);
854
853
  allSchemas[defSub] = schema.definitions[def];
855
854
  }
856
855
  }
@@ -892,7 +891,7 @@ function extractTypes(allSchemas, requiredTypes, referencedSchemas) {
892
891
  function extractTypesFromSchema(allTypes, schema, output) {
893
892
  const additionalTypes = [];
894
893
  if (Is.stringValue(schema.$ref)) {
895
- additionalTypes.push(schema.$ref.replace("#/definitions/", "").replace(/^Partial%3C(.*?)%3E/g, "$1"));
894
+ additionalTypes.push(normaliseTypeName(schema.$ref).replace("#/definitions/", ""));
896
895
  }
897
896
  else if (Is.object(schema.items)) {
898
897
  if (Is.arrayValue(schema.items)) {
@@ -1085,6 +1084,79 @@ async function loadPackages(tsToOpenApiConfig, outputWorkingDir, typeRoots) {
1085
1084
  }
1086
1085
  return restRoutes;
1087
1086
  }
1087
+ /**
1088
+ * Process arrays in the schema object.
1089
+ * @param schemaObject The schema object to process.
1090
+ */
1091
+ function processArrays(schemaObject) {
1092
+ if (Is.object(schemaObject)) {
1093
+ // latest specs have singular items in `items` property
1094
+ // and multiple items in prefixItems, so update the schema accordingly
1095
+ // https://www.learnjsonschema.com/2020-12/applicator/items/
1096
+ // https://www.learnjsonschema.com/2020-12/applicator/prefixitems/
1097
+ const schemaItems = schemaObject.items;
1098
+ if (Is.array(schemaItems) || Is.object(schemaItems)) {
1099
+ schemaObject.prefixItems = ArrayHelper.fromObjectOrArray(schemaItems);
1100
+ delete schemaObject.items;
1101
+ }
1102
+ const additionalItems = schemaObject.additionalItems;
1103
+ if (Is.array(additionalItems) || Is.object(additionalItems)) {
1104
+ schemaObject.items = ArrayHelper.fromObjectOrArray(additionalItems)[0];
1105
+ delete schemaObject.additionalItems;
1106
+ }
1107
+ processSchemaDictionary(schemaObject.properties);
1108
+ processArrays(schemaObject.additionalProperties);
1109
+ processSchemaArray(schemaObject.allOf);
1110
+ processSchemaArray(schemaObject.anyOf);
1111
+ processSchemaArray(schemaObject.oneOf);
1112
+ }
1113
+ }
1114
+ /**
1115
+ * Process arrays in the schema object.
1116
+ * @param schemaDictionary The schema object to process.
1117
+ */
1118
+ function processSchemaDictionary(schemaDictionary) {
1119
+ if (Is.object(schemaDictionary)) {
1120
+ for (const item of Object.values(schemaDictionary)) {
1121
+ if (Is.object(item)) {
1122
+ processArrays(item);
1123
+ }
1124
+ }
1125
+ }
1126
+ }
1127
+ /**
1128
+ * Process arrays in the schema object.
1129
+ * @param schemaArray The schema object to process.
1130
+ */
1131
+ function processSchemaArray(schemaArray) {
1132
+ if (Is.arrayValue(schemaArray)) {
1133
+ for (const item of schemaArray) {
1134
+ if (Is.object(item)) {
1135
+ processArrays(item);
1136
+ }
1137
+ }
1138
+ }
1139
+ }
1140
+ /**
1141
+ * Cleanup TypeScript markers from the type name.
1142
+ * @param typeName The definition string to clean up.
1143
+ * @returns The cleaned up definition string.
1144
+ */
1145
+ function normaliseTypeName(typeName) {
1146
+ // Remove the partial markers
1147
+ let sTypeName = typeName.replace(/^Partial<(.*?)>/g, "$1");
1148
+ sTypeName = sTypeName.replace(/Partial%3CI(.*?)%3E/g, "$1");
1149
+ // Remove the omit markers
1150
+ sTypeName = sTypeName.replace(/^Omit<(.*?),.*>/g, "$1");
1151
+ sTypeName = sTypeName.replace(/Omit%3CI(.*?)%2C.*%3E/g, "$1");
1152
+ // Remove the pick markers
1153
+ sTypeName = sTypeName.replace(/^Pick<(.*?),.*>/g, "$1");
1154
+ sTypeName = sTypeName.replace(/Pick%3CI(.*?)%2C.*%3E/g, "$1");
1155
+ // Cleanup the generic markers
1156
+ sTypeName = sTypeName.replace(/</g, "%3C").replace(/>/g, "%3E");
1157
+ sTypeName = sTypeName.replace(/%3Cunknown%3E/g, "");
1158
+ return sTypeName;
1159
+ }
1088
1160
 
1089
1161
  // Copyright 2024 IOTA Stiftung.
1090
1162
  // SPDX-License-Identifier: Apache-2.0.
@@ -1104,7 +1176,7 @@ class CLI extends CLIBase {
1104
1176
  return this.execute({
1105
1177
  title: "TWIN TypeScript To OpenAPI",
1106
1178
  appName: "ts-to-openapi",
1107
- version: "0.0.1-next.9",
1179
+ version: "0.0.1", // x-release-please-version
1108
1180
  icon: "⚙️ ",
1109
1181
  supportsEnvFiles: false,
1110
1182
  overrideOutputWidth: options?.overrideOutputWidth