openapi-sync 1.0.25 → 2.0.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.
@@ -22,14 +22,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.parseSchemaToType = exports.getEndpointDetails = exports.getSharedComponentName = exports.capitalize = exports.yamlStringToJson = exports.isYamlString = exports.isJson = void 0;
26
+ exports.JSONStringify = exports.getEndpointDetails = exports.capitalize = exports.yamlStringToJson = exports.isYamlString = exports.isJson = void 0;
30
27
  const regex_1 = require("./regex");
31
28
  const yaml = __importStar(require("js-yaml"));
32
- const lodash_1 = __importDefault(require("lodash"));
33
29
  const isJson = (value) => {
34
30
  return ["object"].includes(typeof value) && !(value instanceof Blob);
35
31
  };
@@ -64,8 +60,6 @@ const capitalize = (text) => {
64
60
  return capitalizedWord;
65
61
  };
66
62
  exports.capitalize = capitalize;
67
- const getSharedComponentName = (componentName, componentType) => `IApi${(0, exports.capitalize)(componentName)}`;
68
- exports.getSharedComponentName = getSharedComponentName;
69
63
  const getEndpointDetails = (path, method) => {
70
64
  const pathParts = path.split("/");
71
65
  let name = `${(0, exports.capitalize)(method)}`;
@@ -105,125 +99,24 @@ const getEndpointDetails = (path, method) => {
105
99
  return { name, variables, pathParts };
106
100
  };
107
101
  exports.getEndpointDetails = getEndpointDetails;
108
- const parseSchemaToType = (apiDoc, schema, name, isRequired, options) => {
109
- let overrideName = "";
110
- let componentName = "";
111
- let type = "";
112
- if (schema) {
113
- if (schema.$ref) {
114
- // console.log("Type schema 2");
115
- if (schema.$ref[0] === "#") {
116
- let pathToComponentParts = (schema.$ref || "").split("/");
117
- pathToComponentParts.shift();
118
- const pathToComponent = pathToComponentParts.join(".");
119
- const component = lodash_1.default.get(apiDoc, pathToComponent, null);
120
- // console.log("Type schema 3", pathToComponentParts);
121
- if (component) {
122
- if (component === null || component === void 0 ? void 0 : component.name) {
123
- overrideName = component.name;
124
- }
125
- componentName = pathToComponentParts[pathToComponentParts.length - 1];
126
- // Reference component via import instead of parsing
127
- type += `${(options === null || options === void 0 ? void 0 : options.noSharedImport) ? "" : "Shared."}${(0, exports.getSharedComponentName)(componentName)}`;
128
- // type += `${parseSchemaToType(apiDoc, component, "", isRequired)}`;
129
- }
130
- }
131
- else {
132
- type += "";
133
- //TODO $ref is a uri - use axios to fetch doc
134
- }
135
- }
136
- else if (schema.anyOf) {
137
- type += `(${schema.anyOf
138
- .map((v) => (0, exports.parseSchemaToType)(apiDoc, v, "", isRequired, options))
139
- .join("|")})`;
140
- }
141
- else if (schema.oneOf) {
142
- type += `(${schema.oneOf
143
- .map((v) => (0, exports.parseSchemaToType)(apiDoc, v, "", isRequired, options))
144
- .join("|")})`;
145
- }
146
- else if (schema.allOf) {
147
- type += `(${schema.allOf
148
- .map((v) => (0, exports.parseSchemaToType)(apiDoc, v, "", isRequired, options))
149
- .join("&")})`;
150
- }
151
- else if (schema.items) {
152
- type += `${(0, exports.parseSchemaToType)(apiDoc, schema.items, "", false, options)}[]`;
102
+ const JSONStringify = (obj) => {
103
+ let result = "{";
104
+ const keys = Object.keys(obj);
105
+ for (let i = 0; i < keys.length; i++) {
106
+ const key = keys[i];
107
+ const value = obj[key];
108
+ result += key + ": ";
109
+ if (typeof value === "object" && value !== null) {
110
+ result += (0, exports.JSONStringify)(value);
153
111
  }
154
- else if (schema.properties) {
155
- //parse object key one at a time
156
- const objKeys = Object.keys(schema.properties);
157
- const requiredKeys = schema.required || [];
158
- let typeCnt = "";
159
- objKeys.forEach((key) => {
160
- var _a;
161
- typeCnt += `${(0, exports.parseSchemaToType)(apiDoc, (_a = schema.properties) === null || _a === void 0 ? void 0 : _a[key], key, requiredKeys.includes(key), options)}`;
162
- });
163
- if (typeCnt.length > 0) {
164
- type += `{\n${typeCnt}}`;
165
- }
166
- else {
167
- type += "{[k: string]: any}";
168
- }
112
+ else {
113
+ result += value;
169
114
  }
170
- else if (schema.type) {
171
- if (schema.enum && schema.enum.length > 0) {
172
- if (schema.enum.length > 1)
173
- type += "(";
174
- type += schema.enum
175
- .map((v) => `"${v}"`)
176
- .join("|")
177
- .toString();
178
- if (schema.enum.length > 1)
179
- type += ")";
180
- }
181
- else if (["string", "integer", "number", "array", "boolean"].includes(schema.type)) {
182
- if (["integer", "number"].includes(schema.type)) {
183
- type += `number`;
184
- }
185
- else if (schema.type === "array") {
186
- //Since we would have already parsed the arrays keys above "schema.items" if it exists
187
- type += "any[]";
188
- /* if (schema.items) {
189
- type += `${parseSchemaToType(
190
- apiDoc,
191
- schema.items,
192
- "",
193
- false,
194
- options
195
- )}[]`;
196
- } else {
197
- type += "any[]";
198
- } */
199
- }
200
- else {
201
- type += schema.type;
202
- }
203
- }
204
- else if (schema.type === "object") {
205
- //Since we would have already parsed the object keys above "schema.properties" if it exists
206
- if (schema.additionalProperties) {
207
- type += `{[k: string]: ${(0, exports.parseSchemaToType)(apiDoc, schema.additionalProperties, "", true, options) || "any"}}`;
208
- }
209
- else {
210
- type += "{[k: string]: any}";
211
- }
212
- }
115
+ if (i < keys.length - 1) {
116
+ result += ", ";
213
117
  }
214
118
  }
215
- else {
216
- //Default type to string if no schema provided
217
- type = "string";
218
- }
219
- let _name = overrideName || name;
220
- if ((options === null || options === void 0 ? void 0 : options.useComponentName) && !_name) {
221
- _name = componentName;
222
- }
223
- let typeName = _name ? `\t"${_name}"${isRequired ? "" : "?"}: ` : "";
224
- const nullable = (schema === null || schema === void 0 ? void 0 : schema.nullable) ? " | null" : "";
225
- return type.length > 0
226
- ? `${typeName}${type}${nullable}${_name ? ";\n" : ""}`
227
- : "";
119
+ result += "}";
120
+ return result;
228
121
  };
229
- exports.parseSchemaToType = parseSchemaToType;
122
+ exports.JSONStringify = JSONStringify;
@@ -14,8 +14,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const fs_1 = __importDefault(require("fs"));
16
16
  const path_1 = __importDefault(require("path"));
17
+ const lodash_1 = __importDefault(require("lodash"));
17
18
  const helpers_1 = require("./components/helpers");
18
- const lodash_1 = require("lodash");
19
+ const lodash_2 = require("lodash");
19
20
  const axios_1 = __importDefault(require("axios"));
20
21
  const axios_retry_1 = __importDefault(require("axios-retry"));
21
22
  const openapi_core_1 = require("@redocly/openapi-core");
@@ -37,7 +38,8 @@ const apiClient = axios_1.default.create({
37
38
  return retryCount * 1000; // Exponential back-off: 1s, 2s, 3s, etc.
38
39
  },
39
40
  });
40
- const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void 0, void 0, function* () {
41
+ const OpenapiSync = (apiUrl, apiName, config, refetchInterval) => __awaiter(void 0, void 0, void 0, function* () {
42
+ var _a, _b, _c, _d;
41
43
  const specResponse = yield apiClient.get(apiUrl);
42
44
  const redoclyConfig = yield (0, openapi_core_1.createConfig)({
43
45
  extends: ["minimal"],
@@ -49,10 +51,160 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
49
51
  source,
50
52
  config: redoclyConfig,
51
53
  });
52
- // Load config file
53
- const config = require(path_1.default.join(rootUsingCwd, "openapi.sync.json"));
54
54
  const folderPath = path_1.default.join(config.folder || "", apiName);
55
55
  const spec = lintResults.bundle.parsed;
56
+ const typePrefix = typeof ((_b = (_a = config === null || config === void 0 ? void 0 : config.types) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.prefix) === "string"
57
+ ? config.types.name.prefix
58
+ : "I";
59
+ const endpointPrefix = typeof ((_d = (_c = config === null || config === void 0 ? void 0 : config.endpoints) === null || _c === void 0 ? void 0 : _c.name) === null || _d === void 0 ? void 0 : _d.prefix) === "string"
60
+ ? config.endpoints.name.prefix
61
+ : "";
62
+ const getSharedComponentName = (componentName, componentType) => {
63
+ var _a, _b;
64
+ if ((_b = (_a = config === null || config === void 0 ? void 0 : config.types) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.format) {
65
+ const formattedName = config.types.name.format("shared", {
66
+ name: componentName,
67
+ });
68
+ if (formattedName)
69
+ return `${typePrefix}${formattedName}`;
70
+ }
71
+ return `${typePrefix}${(0, helpers_1.capitalize)(componentName)}`;
72
+ };
73
+ const parseSchemaToType = (apiDoc, schema, name, isRequired, options) => {
74
+ let overrideName = "";
75
+ let componentName = "";
76
+ let type = "";
77
+ if (schema) {
78
+ if (schema.$ref) {
79
+ if (schema.$ref[0] === "#") {
80
+ let pathToComponentParts = (schema.$ref || "").split("/");
81
+ pathToComponentParts.shift();
82
+ const partsClone = [...pathToComponentParts];
83
+ partsClone.pop();
84
+ const pathToComponent = pathToComponentParts;
85
+ const component = lodash_1.default.get(apiDoc, pathToComponent, null);
86
+ if (component) {
87
+ if (component === null || component === void 0 ? void 0 : component.name) {
88
+ overrideName = component.name;
89
+ }
90
+ componentName =
91
+ pathToComponentParts[pathToComponentParts.length - 1];
92
+ let name = getSharedComponentName(componentName);
93
+ if (name.includes(".")) {
94
+ const nameParts = name.split(".");
95
+ name = nameParts
96
+ .map((part, i) => {
97
+ if (i === 0) {
98
+ return part;
99
+ }
100
+ return `["${part}"]`;
101
+ })
102
+ .join("");
103
+ }
104
+ // Reference component via import instead of parsing
105
+ type += `${(options === null || options === void 0 ? void 0 : options.noSharedImport) ? "" : "Shared."}${name}`;
106
+ // type += `${parseSchemaToType(apiDoc, component, "", isRequired)}`;
107
+ }
108
+ }
109
+ else {
110
+ type += "";
111
+ //TODO $ref is a uri - use axios to fetch doc
112
+ }
113
+ }
114
+ else if (schema.anyOf) {
115
+ type += `(${schema.anyOf
116
+ .map((v) => parseSchemaToType(apiDoc, v, "", isRequired, options))
117
+ .join("|")})`;
118
+ }
119
+ else if (schema.oneOf) {
120
+ type += `(${schema.oneOf
121
+ .map((v) => parseSchemaToType(apiDoc, v, "", isRequired, options))
122
+ .join("|")})`;
123
+ }
124
+ else if (schema.allOf) {
125
+ type += `(${schema.allOf
126
+ .map((v) => parseSchemaToType(apiDoc, v, "", isRequired, options))
127
+ .join("&")})`;
128
+ }
129
+ else if (schema.items) {
130
+ type += `${parseSchemaToType(apiDoc, schema.items, "", false, options)}[]`;
131
+ }
132
+ else if (schema.properties) {
133
+ //parse object key one at a time
134
+ const objKeys = Object.keys(schema.properties);
135
+ const requiredKeys = schema.required || [];
136
+ let typeCnt = "";
137
+ objKeys.forEach((key) => {
138
+ var _a;
139
+ typeCnt += `${parseSchemaToType(apiDoc, (_a = schema.properties) === null || _a === void 0 ? void 0 : _a[key], key, requiredKeys.includes(key), options)}`;
140
+ });
141
+ if (typeCnt.length > 0) {
142
+ type += `{\n${typeCnt}}`;
143
+ }
144
+ else {
145
+ type += "{[k: string]: any}";
146
+ }
147
+ }
148
+ else if (schema.enum && schema.enum.length > 0) {
149
+ if (schema.enum.length > 1)
150
+ type += "(";
151
+ schema.enum.forEach((v) => {
152
+ let val = JSON.stringify(v);
153
+ if (val)
154
+ type += `|${val}`;
155
+ });
156
+ if (schema.enum.length > 1)
157
+ type += ")";
158
+ }
159
+ else if (schema.type) {
160
+ if (["string", "integer", "number", "array", "boolean"].includes(schema.type)) {
161
+ if (["integer", "number"].includes(schema.type)) {
162
+ type += `number`;
163
+ }
164
+ else if (schema.type === "array") {
165
+ //Since we would have already parsed the arrays keys above "schema.items" if it exists
166
+ type += "any[]";
167
+ /* if (schema.items) {
168
+ type += `${parseSchemaToType(
169
+ apiDoc,
170
+ schema.items,
171
+ "",
172
+ false,
173
+ options
174
+ )}[]`;
175
+ } else {
176
+ type += "any[]";
177
+ } */
178
+ }
179
+ else {
180
+ type += schema.type;
181
+ }
182
+ }
183
+ else if (schema.type === "object") {
184
+ //Since we would have already parsed the object keys above "schema.properties" if it exists
185
+ if (schema.additionalProperties) {
186
+ type += `{[k: string]: ${parseSchemaToType(apiDoc, schema.additionalProperties, "", true, options) || "any"}}`;
187
+ }
188
+ else {
189
+ type += "{[k: string]: any}";
190
+ }
191
+ }
192
+ }
193
+ }
194
+ else {
195
+ //Default type to string if no schema provided
196
+ type = "string";
197
+ }
198
+ let _name = overrideName || name;
199
+ if ((options === null || options === void 0 ? void 0 : options.useComponentName) && !_name) {
200
+ _name = componentName;
201
+ }
202
+ let typeName = _name ? `\t"${_name}"${isRequired ? "" : "?"}: ` : "";
203
+ const nullable = (schema === null || schema === void 0 ? void 0 : schema.nullable) ? " | null" : "";
204
+ return type.length > 0
205
+ ? `${typeName}${type}${nullable}${_name ? ";\n" : ""}`
206
+ : "";
207
+ };
56
208
  // auto update only on dev
57
209
  if (refetchInterval && !isNaN(refetchInterval) && refetchInterval > 0) {
58
210
  if (!(process.env.NODE_ENV &&
@@ -61,12 +213,12 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
61
213
  if (fetchTimeout[apiName])
62
214
  clearTimeout(fetchTimeout[apiName]);
63
215
  // set next request timeout
64
- fetchTimeout[apiName] = setTimeout(() => OpenapiSync(apiUrl, apiName, refetchInterval), refetchInterval);
216
+ fetchTimeout[apiName] = setTimeout(() => OpenapiSync(apiUrl, apiName, config, refetchInterval), refetchInterval);
65
217
  }
66
218
  }
67
219
  // compare new spec with old spec, continuing only if spec it different
68
220
  const prevSpec = (0, state_1.getState)(apiName);
69
- if ((0, lodash_1.isEqual)(prevSpec, spec))
221
+ if ((0, lodash_2.isEqual)(prevSpec, spec))
70
222
  return;
71
223
  (0, state_1.setState)(apiName, spec);
72
224
  let endpointsFileContent = "";
@@ -86,10 +238,11 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
86
238
  ].includes(key)) {
87
239
  // Create components (shared) types
88
240
  const components = spec.components[key];
241
+ const componentInterfaces = {};
89
242
  const contentKeys = Object.keys(components);
90
243
  // only need 1 schema so will us the first schema provided
91
244
  contentKeys.forEach((contentKey) => {
92
- var _a, _b;
245
+ var _a;
93
246
  /* const schema = (() => {
94
247
  switch (key) {
95
248
  case "parameters":
@@ -101,16 +254,43 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
101
254
  const schema = (((_a = components[contentKey]) === null || _a === void 0 ? void 0 : _a.schema)
102
255
  ? components[contentKey].schema
103
256
  : components[contentKey]);
104
- const typeCnt = `${(0, helpers_1.parseSchemaToType)(spec, schema, "", true, {
257
+ const typeCnt = `${parseSchemaToType(spec, schema, "", true, {
105
258
  noSharedImport: true,
106
259
  useComponentName: ["parameters"].includes(key),
107
260
  })}`;
108
261
  if (typeCnt) {
109
- sharedTypesFileContent[key] =
110
- ((_b = sharedTypesFileContent[key]) !== null && _b !== void 0 ? _b : "") +
111
- `export type ${(0, helpers_1.getSharedComponentName)(contentKey)} = ${typeCnt};\n`;
262
+ const parts = contentKey.split(".");
263
+ let currentLevel = componentInterfaces;
264
+ // Navigate or create the nested structure
265
+ for (let i = 0; i < parts.length; i++) {
266
+ const part = parts[i];
267
+ if (i < parts.length - 1) {
268
+ // If it's not the last part, create a nested object if it doesn't exist
269
+ if (!(part in currentLevel)) {
270
+ currentLevel[part] = {}; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentInterfaces
271
+ }
272
+ currentLevel = currentLevel[part]; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentInterfaces
273
+ }
274
+ else {
275
+ // This is the last part, assign the original schema value
276
+ currentLevel[part] = typeCnt; //<== This rely on js ability to assign value to origianl object by reference, so this assignment will be reflected in componentInterfaces
277
+ }
278
+ }
112
279
  }
113
280
  });
281
+ // Generate TypeScript interfaces for each component
282
+ Object.keys(componentInterfaces).forEach((key) => {
283
+ var _a;
284
+ const name = getSharedComponentName(key);
285
+ const cnt = componentInterfaces[key];
286
+ sharedTypesFileContent[key] =
287
+ ((_a = sharedTypesFileContent[key]) !== null && _a !== void 0 ? _a : "") +
288
+ "export type " +
289
+ name +
290
+ " = " +
291
+ (typeof cnt === "string" ? cnt : (0, helpers_1.JSONStringify)(cnt)) +
292
+ ";\n";
293
+ });
114
294
  }
115
295
  });
116
296
  }
@@ -120,17 +300,17 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
120
300
  const contentKeys = Object.keys(requestBody.content);
121
301
  // only need 1 schema so will us the first schema provided
122
302
  if (contentKeys[0] && requestBody.content[contentKeys[0]].schema) {
123
- typeCnt += `${(0, helpers_1.parseSchemaToType)(spec, requestBody.content[contentKeys[0]].schema, "")}`;
303
+ typeCnt += `${parseSchemaToType(spec, requestBody.content[contentKeys[0]].schema, "")}`;
124
304
  }
125
305
  }
126
306
  return typeCnt;
127
307
  };
128
308
  const treatEndpointUrl = (endpointUrl) => {
129
- var _a, _b;
309
+ var _a, _b, _c, _d, _e;
130
310
  if (((_b = (_a = config === null || config === void 0 ? void 0 : config.endpoints) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.replaceWords) &&
131
311
  Array.isArray(config.endpoints.value.replaceWords)) {
132
312
  let newEndpointUrl = endpointUrl;
133
- config.endpoints.value.replaceWords.forEach((replaceWord, indx) => {
313
+ (_e = (_d = (_c = config === null || config === void 0 ? void 0 : config.endpoints) === null || _c === void 0 ? void 0 : _c.value) === null || _d === void 0 ? void 0 : _d.replaceWords) === null || _e === void 0 ? void 0 : _e.forEach((replaceWord, indx) => {
134
314
  const regexp = new RegExp(replaceWord.replace, "g");
135
315
  newEndpointUrl = newEndpointUrl.replace(regexp, replaceWord.with || "");
136
316
  });
@@ -142,9 +322,11 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
142
322
  };
143
323
  Object.keys(spec.paths || {}).forEach((endpointPath) => {
144
324
  const endpointSpec = spec.paths[endpointPath];
325
+ // console.log("Endpoint Path:", { endpointPath, endpointSpec });
145
326
  const endpointMethods = Object.keys(endpointSpec);
146
- endpointMethods.forEach((method) => {
147
- var _a, _b, _c, _d, _e, _f;
327
+ endpointMethods.forEach((_method) => {
328
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
329
+ const method = _method;
148
330
  const endpoint = (0, helpers_1.getEndpointDetails)(endpointPath, method);
149
331
  const endpointUrlTxt = endpoint.pathParts
150
332
  .map((part) => {
@@ -173,38 +355,85 @@ const OpenapiSync = (apiUrl, apiName, refetchInterval) => __awaiter(void 0, void
173
355
  }
174
356
  //treat endpoint url
175
357
  endpointUrl = treatEndpointUrl(endpointUrl);
358
+ let name = `${endpoint.name}`;
359
+ if ((_b = (_a = config === null || config === void 0 ? void 0 : config.endpoints) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.format) {
360
+ const formattedName = config.endpoints.name.format({
361
+ method,
362
+ path: endpointPath,
363
+ summary: (_c = endpointSpec[method]) === null || _c === void 0 ? void 0 : _c.summary,
364
+ });
365
+ if (formattedName)
366
+ name = formattedName;
367
+ }
176
368
  // Add the endpoint url
177
- endpointsFileContent += `export const ${endpoint.name} = ${endpointUrl};
369
+ endpointsFileContent += `export const ${endpointPrefix}${name} = ${endpointUrl};
178
370
  `;
179
- if ((_a = endpointSpec[method]) === null || _a === void 0 ? void 0 : _a.parameters) {
371
+ if ((_d = endpointSpec[method]) === null || _d === void 0 ? void 0 : _d.parameters) {
180
372
  // create query parameters types
181
- const parameters = (_b = endpointSpec[method]) === null || _b === void 0 ? void 0 : _b.parameters;
373
+ const parameters = (_e = endpointSpec[method]) === null || _e === void 0 ? void 0 : _e.parameters;
182
374
  let typeCnt = "";
183
375
  parameters.forEach((param, i) => {
184
376
  if (param.$ref || (param.in === "query" && param.name)) {
185
- typeCnt += `${(0, helpers_1.parseSchemaToType)(spec, param.$ref ? param : param.schema, param.name || "", param.required)}`;
377
+ typeCnt += `${parseSchemaToType(spec, param.$ref ? param : param.schema, param.name || "", param.required)}`;
186
378
  }
187
379
  });
188
380
  if (typeCnt) {
189
- typesFileContent += `export type I${endpoint.name}Query = {\n${typeCnt}};\n`;
381
+ let name = `${endpoint.name}Query`;
382
+ if ((_g = (_f = config === null || config === void 0 ? void 0 : config.types) === null || _f === void 0 ? void 0 : _f.name) === null || _g === void 0 ? void 0 : _g.format) {
383
+ const formattedName = config.types.name.format("endpoint", {
384
+ code: "",
385
+ type: "query",
386
+ method,
387
+ path: endpointPath,
388
+ summary: (_h = endpointSpec[method]) === null || _h === void 0 ? void 0 : _h.summary,
389
+ });
390
+ if (formattedName)
391
+ name = formattedName;
392
+ }
393
+ typesFileContent += `export type ${typePrefix}${name} = {\n${typeCnt}};\n`;
190
394
  }
191
395
  }
192
- if ((_c = endpointSpec[method]) === null || _c === void 0 ? void 0 : _c.requestBody) {
396
+ if ((_j = endpointSpec[method]) === null || _j === void 0 ? void 0 : _j.requestBody) {
193
397
  //create requestBody types
194
- const requestBody = (_d = endpointSpec[method]) === null || _d === void 0 ? void 0 : _d.requestBody;
398
+ const requestBody = (_k = endpointSpec[method]) === null || _k === void 0 ? void 0 : _k.requestBody;
195
399
  let typeCnt = getBodySchemaType(requestBody);
196
400
  if (typeCnt) {
197
- typesFileContent += `export type I${endpoint.name}DTO = ${typeCnt};\n`;
401
+ let name = `${endpoint.name}DTO`;
402
+ if ((_m = (_l = config === null || config === void 0 ? void 0 : config.types) === null || _l === void 0 ? void 0 : _l.name) === null || _m === void 0 ? void 0 : _m.format) {
403
+ const formattedName = config.types.name.format("endpoint", {
404
+ code: "",
405
+ type: "dto",
406
+ method,
407
+ path: endpointPath,
408
+ summary: (_o = endpointSpec[method]) === null || _o === void 0 ? void 0 : _o.summary,
409
+ });
410
+ if (formattedName)
411
+ name = formattedName;
412
+ }
413
+ typesFileContent += `export type ${typePrefix}${name} = ${typeCnt};\n`;
198
414
  }
199
415
  }
200
- if ((_e = endpointSpec[method]) === null || _e === void 0 ? void 0 : _e.responses) {
416
+ if ((_p = endpointSpec[method]) === null || _p === void 0 ? void 0 : _p.responses) {
201
417
  // create request response types
202
- const responses = (_f = endpointSpec[method]) === null || _f === void 0 ? void 0 : _f.responses;
418
+ const responses = (_q = endpointSpec[method]) === null || _q === void 0 ? void 0 : _q.responses;
203
419
  const resCodes = Object.keys(responses);
204
420
  resCodes.forEach((code) => {
421
+ var _a, _b, _c;
205
422
  let typeCnt = getBodySchemaType(responses[code]);
206
423
  if (typeCnt) {
207
- typesFileContent += `export type I${endpoint.name}${code}Response = ${typeCnt};\n`;
424
+ let name = `${endpoint.name}${code}Response`;
425
+ if ((_b = (_a = config === null || config === void 0 ? void 0 : config.types) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.format) {
426
+ const formattedName = config.types.name.format("endpoint", {
427
+ code,
428
+ type: "response",
429
+ method,
430
+ path: endpointPath,
431
+ summary: (_c = endpointSpec[method]) === null || _c === void 0 ? void 0 : _c.summary,
432
+ });
433
+ if (formattedName)
434
+ name = formattedName;
435
+ }
436
+ typesFileContent += `export type ${typePrefix}${name} = ${typeCnt};\n`;
208
437
  }
209
438
  });
210
439
  }
package/dist/index.js CHANGED
@@ -21,7 +21,20 @@ dotenv_1.default.config();
21
21
  const rootUsingCwd = process.cwd();
22
22
  const Init = (options) => __awaiter(void 0, void 0, void 0, function* () {
23
23
  // Load config file
24
- const config = require(path_1.default.join(rootUsingCwd, "openapi.sync.json"));
24
+ let configJS, configJson;
25
+ try {
26
+ configJS = require(path_1.default.join(rootUsingCwd, "openapi.sync.js"));
27
+ }
28
+ catch (e) {
29
+ // console.log(e);
30
+ }
31
+ try {
32
+ configJson = require(path_1.default.join(rootUsingCwd, "openapi.sync.json"));
33
+ }
34
+ catch (e) {
35
+ // console.log(e);
36
+ }
37
+ const config = configJS || configJson;
25
38
  const apiNames = Object.keys(config.api);
26
39
  const refetchInterval = options &&
27
40
  "refetchInterval" in options &&
@@ -32,7 +45,7 @@ const Init = (options) => __awaiter(void 0, void 0, void 0, function* () {
32
45
  for (let i = 0; i < apiNames.length; i += 1) {
33
46
  const apiName = apiNames[i];
34
47
  const apiUrl = config.api[apiName];
35
- (0, Openapi_sync_1.default)(apiUrl, apiName, refetchInterval);
48
+ (0, Openapi_sync_1.default)(apiUrl, apiName, config, refetchInterval);
36
49
  }
37
50
  });
38
51
  exports.Init = Init;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openapi-sync",
3
- "version": "1.0.25",
3
+ "version": "2.0.0",
4
4
  "description": "A developer-friendly tool designed to keep your API up-to-date by leveraging OpenAPI schemas. It automates the generation of endpoint URIs and type definitions, including shared types, directly from your OpenAPI specification.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,6 +24,7 @@
24
24
  "bin",
25
25
  "dist",
26
26
  "db.json",
27
+ "types.ts",
27
28
  "LICENSE",
28
29
  "README.md",
29
30
  "package.json"
@@ -31,7 +32,7 @@
31
32
  "scripts": {
32
33
  "test": "echo \"Error: no test specified\"",
33
34
  "build": "tsc",
34
- "publish-package": "npm run build && npm version patch && npm publish",
35
+ "publish-package": "npm run build && npm version major && npm publish",
35
36
  "start": "npm run build && openapi-sync"
36
37
  },
37
38
  "author": "P-Technologies",
package/types.ts ADDED
@@ -0,0 +1,93 @@
1
+ import { Method } from "axios";
2
+
3
+ export type IOpenApiSpec = Record<"openapi", string> & Record<string, any>;
4
+
5
+ export type IOpenApSchemaSpec = {
6
+ nullable?: boolean;
7
+ type: "string" | "integer" | "number" | "array" | "object" | "boolean";
8
+ example?: any;
9
+ enum?: string[];
10
+ format?: string;
11
+ items?: IOpenApSchemaSpec;
12
+ required?: string[];
13
+ $ref?: string;
14
+ properties?: Record<string, IOpenApSchemaSpec>;
15
+ additionalProperties?: IOpenApSchemaSpec;
16
+ anyOf?: IOpenApSchemaSpec[];
17
+ oneOf?: IOpenApSchemaSpec[];
18
+ allOf?: IOpenApSchemaSpec[];
19
+ };
20
+
21
+ export type IOpenApiParameterSpec = {
22
+ $ref?: string;
23
+ name: string;
24
+ in: string;
25
+ enum?: string[];
26
+ description?: string;
27
+ required?: boolean;
28
+ deprecated?: boolean;
29
+ allowEmptyValue?: boolean;
30
+ style?: string;
31
+ explode?: boolean;
32
+ allowReserved?: boolean;
33
+ schema?: IOpenApSchemaSpec;
34
+ example?: any;
35
+ examples?: any[];
36
+ };
37
+
38
+ export type IOpenApiMediaTypeSpec = {
39
+ schema?: IOpenApSchemaSpec;
40
+ example?: any;
41
+ examples?: any[];
42
+ encoding?: any;
43
+ };
44
+
45
+ export type IOpenApiRequestBodySpec = {
46
+ description?: string;
47
+ required?: boolean;
48
+ content: Record<string, IOpenApiMediaTypeSpec>;
49
+ };
50
+
51
+ export type IOpenApiResponseSpec = Record<string, IOpenApiRequestBodySpec>;
52
+
53
+ export type IConfigReplaceWord = {
54
+ /** string and regular expression as a string*/
55
+ replace: string;
56
+ with: string;
57
+ type?: "endpoint" | "type";
58
+ };
59
+
60
+ export type IConfig = {
61
+ refetchInterval?: number;
62
+ folder?: string;
63
+ api: Record<string, string>;
64
+ types?: {
65
+ name?: {
66
+ prefix?: string;
67
+ format?: (
68
+ source: "shared" | "endpoint",
69
+ data: {
70
+ name?: string;
71
+ type?: "response" | "dto" | "query";
72
+ code?: string;
73
+ method?: Method;
74
+ path?: string;
75
+ summary?: string;
76
+ }
77
+ ) => string | null | undefined;
78
+ };
79
+ };
80
+ endpoints?: {
81
+ value?: {
82
+ replaceWords?: IConfigReplaceWord[];
83
+ };
84
+ name?: {
85
+ format?: (data: {
86
+ method: Method;
87
+ path: string;
88
+ summary: string;
89
+ }) => string | null;
90
+ prefix?: string;
91
+ };
92
+ };
93
+ };
File without changes