@accelbyte/codegen 1.0.0-alpha.1 → 1.0.0-alpha.3
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/README.md +33 -7
- package/dist/accelbyte-codegen.js +38 -36
- package/dist/accelbyte-codegen.js.map +1 -1
- package/dist/accelbyte-codegen.mjs +4 -4
- package/dist/accelbyte-codegen.mjs.map +1 -1
- package/package.json +1 -1
- package/CHANGELOG.md +0 -40
package/README.md
CHANGED
|
@@ -2,7 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
Odin Code Generator is a utility tool to generate network calls in Typescript for each of the endpoints on Swagger's JSON document found in Justice backend services
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## CLI
|
|
6
|
+
This codegen build a CLI called `accelbyte-codegen` that will be used to generate code from given config.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
Commands:
|
|
10
|
+
accelbyte-codegen download-swaggers Download swaggers JSON files
|
|
11
|
+
accelbyte-codegen generate-code Generate code based on downloaded swagger
|
|
12
|
+
files
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--version Show version number [boolean]
|
|
16
|
+
--config Config file providing backend services URL. [string] [required]
|
|
17
|
+
--swaggersOutput Output path for downloaded swaggers JSON files. [string] [required]
|
|
18
|
+
--output Output path for generated code. Required for generate-code [string]
|
|
19
|
+
--admin Only generate /admin endpoints. [boolean] [default: false]
|
|
20
|
+
--help Show help [boolean]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Config file
|
|
24
|
+
Provide swaggers url you wish to generate, store it in .json format file.
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
[
|
|
28
|
+
["iam", "Iam", "iam.json", "https://example.com/iam/apidocs/api.json"]
|
|
29
|
+
]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## How to Generate
|
|
33
|
+
1. Provide config
|
|
34
|
+
2. Download swagger files
|
|
35
|
+
``accelbyte-codegen download-swaggers --config ./config.json --swaggersOutput ./swaggers``
|
|
36
|
+
3. Generate code from swagger files
|
|
37
|
+
``accelbyte-codegen generate-code --config ./config.json --swaggersOutput ./swaggers --output ./sdk``
|
|
6
38
|
|
|
7
39
|
## JSON Patch
|
|
8
40
|
Inside the directory `packages/od-codegen/src/swaggers`, there are also JSON Patch that will patch the Swagger document. The patches will adjust the endpoints so that it will produce the proper functions to match the actual backend service.
|
|
@@ -135,9 +167,3 @@ patch:
|
|
|
135
167
|
]
|
|
136
168
|
}
|
|
137
169
|
```
|
|
138
|
-
|
|
139
|
-
# How to generate
|
|
140
|
-
So the flow to generate/regenerate Swagger JSON, here's what needs to be done.
|
|
141
|
-
1. Download the JSON files and store it `packages/od-codegen/src/swaggers`
|
|
142
|
-
2. Run `yarn build:codegen`
|
|
143
|
-
3. See that `packages/od-web-sdk/src/generated` is changed
|
|
@@ -22,12 +22,14 @@ function _interopNamespace(e) {
|
|
|
22
22
|
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
23
23
|
Object.defineProperty(n, k, d.get ? d : {
|
|
24
24
|
enumerable: true,
|
|
25
|
-
get: function () {
|
|
25
|
+
get: function () {
|
|
26
|
+
return e[k];
|
|
27
|
+
}
|
|
26
28
|
});
|
|
27
29
|
}
|
|
28
30
|
});
|
|
29
31
|
}
|
|
30
|
-
n[
|
|
32
|
+
n['default'] = e;
|
|
31
33
|
return Object.freeze(n);
|
|
32
34
|
}
|
|
33
35
|
|
|
@@ -64,7 +66,7 @@ class CliParser {
|
|
|
64
66
|
const configPath = CliParser.getConfigPath();
|
|
65
67
|
if (!configPath)
|
|
66
68
|
throw new Error("Missing config file");
|
|
67
|
-
const config = JSON.parse(fs__default[
|
|
69
|
+
const config = JSON.parse(fs__default['default'].readFileSync(configPath, "utf8"));
|
|
68
70
|
if (!SwaggersConfig.safeParse(config).success) {
|
|
69
71
|
throw new Error("Wrong config file format");
|
|
70
72
|
}
|
|
@@ -189,7 +191,7 @@ class ParserUtils {
|
|
|
189
191
|
ref = ref.slice(0, -1);
|
|
190
192
|
}
|
|
191
193
|
const val = ref.slice(ref.lastIndexOf("/") + 1);
|
|
192
|
-
return ___default[
|
|
194
|
+
return ___default['default'].upperFirst(___default['default'].camelCase(val));
|
|
193
195
|
};
|
|
194
196
|
static parseAttributeType = (name, definition) => {
|
|
195
197
|
const required = definition.required ? "" : "?";
|
|
@@ -281,7 +283,7 @@ class ParserUtils {
|
|
|
281
283
|
}
|
|
282
284
|
}
|
|
283
285
|
let classMethod = httpMethod + "/" + replacedIdsPath;
|
|
284
|
-
classMethod = ___default[
|
|
286
|
+
classMethod = ___default['default'].camelCase(classMethod);
|
|
285
287
|
classMethod = classMethod.replace("PublicNamespacesByNamespace", "");
|
|
286
288
|
classMethod = classMethod.replace("AdminNamespacesByNamespace", "Admin");
|
|
287
289
|
const searchWord = "NamespacesByNamespace";
|
|
@@ -295,7 +297,7 @@ class ParserUtils {
|
|
|
295
297
|
static getBodyParams(parametersArray) {
|
|
296
298
|
if (!parametersArray)
|
|
297
299
|
return [];
|
|
298
|
-
if (!___default[
|
|
300
|
+
if (!___default['default'].isArray(parametersArray) && parametersArray)
|
|
299
301
|
return [parametersArray].filter((p) => p.in === "body" || p.in === "formData");
|
|
300
302
|
return parametersArray.filter((p) => p.in === "body" || p.in === "formData");
|
|
301
303
|
}
|
|
@@ -312,25 +314,25 @@ class ParserUtils {
|
|
|
312
314
|
return res;
|
|
313
315
|
}
|
|
314
316
|
static mkdirIfNotExist(dirToCreate) {
|
|
315
|
-
if (!fs__default[
|
|
316
|
-
fs__default[
|
|
317
|
+
if (!fs__default['default'].existsSync(dirToCreate)) {
|
|
318
|
+
fs__default['default'].mkdirSync(dirToCreate, { recursive: true });
|
|
317
319
|
}
|
|
318
320
|
}
|
|
319
321
|
static writeClassFile(distDir, apiName, apiBuffer, imports) {
|
|
320
322
|
const fileContent = templateClass(apiName, apiBuffer, imports);
|
|
321
|
-
fs__default[
|
|
323
|
+
fs__default['default'].writeFileSync(`${distDir}/${apiName}.ts`, ParserUtils.prependCopyrightHeader(fileContent));
|
|
322
324
|
}
|
|
323
325
|
static writeJsdocFile(distDir, nameArray, apiBuffer) {
|
|
324
326
|
const jsdocFile = templateJsdocFile(nameArray[0], apiBuffer);
|
|
325
|
-
fs__default[
|
|
327
|
+
fs__default['default'].writeFileSync(`${distDir}/docs/${nameArray[0]}.md`, jsdocFile);
|
|
326
328
|
}
|
|
327
329
|
static writeDefinitionFile(distDir, name, buffer) {
|
|
328
330
|
ParserUtils.mkdirIfNotExist(distDir);
|
|
329
|
-
fs__default[
|
|
331
|
+
fs__default['default'].writeFileSync(path__default['default'].join(distDir, `${name}.ts`), ParserUtils.prependCopyrightHeader(buffer));
|
|
330
332
|
}
|
|
331
333
|
static writeAllImportsFile(distDir, buffer, isAdminWebSdk) {
|
|
332
334
|
ParserUtils.mkdirIfNotExist(distDir);
|
|
333
|
-
fs__default[
|
|
335
|
+
fs__default['default'].writeFileSync(path__default['default'].join(distDir, `all-${isAdminWebSdk ? "admin" : "public"}-imports.ts`), ParserUtils.prependCopyrightHeader(buffer));
|
|
334
336
|
}
|
|
335
337
|
static toCamelCase(str) {
|
|
336
338
|
return str.split("/").map(function(word, index) {
|
|
@@ -356,17 +358,17 @@ class ParserUtils {
|
|
|
356
358
|
});
|
|
357
359
|
}
|
|
358
360
|
static applyPatchIfExists(swaggerFilePath, possibleSwaggerPatchFilePath, swaggerPatchedFilePath, swaggerPatchedDir) {
|
|
359
|
-
if (!fs__default[
|
|
360
|
-
fs__default[
|
|
361
|
+
if (!fs__default['default'].existsSync(swaggerPatchedDir)) {
|
|
362
|
+
fs__default['default'].mkdirSync(swaggerPatchedDir, { recursive: true });
|
|
361
363
|
}
|
|
362
|
-
if (!fs__default[
|
|
363
|
-
fs__default[
|
|
364
|
+
if (!fs__default['default'].existsSync(possibleSwaggerPatchFilePath)) {
|
|
365
|
+
fs__default['default'].copyFileSync(swaggerFilePath, swaggerPatchedFilePath);
|
|
364
366
|
return;
|
|
365
367
|
}
|
|
366
|
-
const swaggerContent = JSON.parse(fs__default[
|
|
367
|
-
const swaggerPatchFileContent = JSON.parse(fs__default[
|
|
368
|
+
const swaggerContent = JSON.parse(fs__default['default'].readFileSync(swaggerFilePath, "utf8"));
|
|
369
|
+
const swaggerPatchFileContent = JSON.parse(fs__default['default'].readFileSync(possibleSwaggerPatchFilePath, "utf8"));
|
|
368
370
|
const { newDocument } = fastJsonPatch.applyPatch(swaggerContent, swaggerPatchFileContent);
|
|
369
|
-
fs__default[
|
|
371
|
+
fs__default['default'].writeFileSync(swaggerPatchedFilePath, JSON.stringify(newDocument, null, 2));
|
|
370
372
|
}
|
|
371
373
|
static mapKeys(map_) {
|
|
372
374
|
const methods_ = [];
|
|
@@ -495,8 +497,8 @@ const templateMethod = (classMethod, description, httpMethod, path, pathParams,
|
|
|
495
497
|
if (!this.cache) {
|
|
496
498
|
return SdkCache.withoutCache(res)
|
|
497
499
|
}
|
|
498
|
-
const
|
|
499
|
-
return SdkCache.withCache(
|
|
500
|
+
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
501
|
+
return SdkCache.withCache(cacheKey, res)
|
|
500
502
|
}
|
|
501
503
|
`;
|
|
502
504
|
isGuardInvoked = true;
|
|
@@ -513,8 +515,8 @@ const templateMethod = (classMethod, description, httpMethod, path, pathParams,
|
|
|
513
515
|
if (!this.cache) {
|
|
514
516
|
return SdkCache.withoutCache(res)
|
|
515
517
|
}
|
|
516
|
-
const
|
|
517
|
-
return SdkCache.withCache(
|
|
518
|
+
const cacheKey = url + CodeGenUtil.hashCode(JSON.stringify({ params }))
|
|
519
|
+
return SdkCache.withCache(cacheKey, res)
|
|
518
520
|
}
|
|
519
521
|
`;
|
|
520
522
|
isGuardInvoked = true;
|
|
@@ -778,7 +780,7 @@ const extractEnumObject = (type, isRequired, enumArr) => {
|
|
|
778
780
|
};
|
|
779
781
|
|
|
780
782
|
class CodeGenerator {
|
|
781
|
-
static getPatchedDir = () => path__default[
|
|
783
|
+
static getPatchedDir = () => path__default['default'].join(CliParser.getSwaggersOutputPath(), "patched");
|
|
782
784
|
static getGeneratedPublicFolder = () => `${CliParser.getOutputPath()}/generated-public`;
|
|
783
785
|
static getGeneratedAdminFolder = () => `${CliParser.getOutputPath()}/generated-admin`;
|
|
784
786
|
static iterateApi = (api) => {
|
|
@@ -802,7 +804,7 @@ class CodeGenerator {
|
|
|
802
804
|
const description = e.description;
|
|
803
805
|
const isDeprecated = e.deprecated;
|
|
804
806
|
const responseClass = ParserUtils.get2xxResponse(e.responses, path2);
|
|
805
|
-
const className = ___default[
|
|
807
|
+
const className = ___default['default'].upperFirst(___default['default'].camelCase(tag));
|
|
806
808
|
classImports[className] = classImports[className] ? classImports[className] : {};
|
|
807
809
|
if (!isDeprecated) {
|
|
808
810
|
if (responseClass) {
|
|
@@ -831,11 +833,11 @@ class CodeGenerator {
|
|
|
831
833
|
static main = async (nameArray) => {
|
|
832
834
|
const serviceName = nameArray[0];
|
|
833
835
|
const swaggerFile = nameArray[2];
|
|
834
|
-
const parser = new SwaggerParser__default[
|
|
836
|
+
const parser = new SwaggerParser__default['default']();
|
|
835
837
|
const generatedFolder = CliParser.isAdmin() ? CodeGenerator.getGeneratedAdminFolder() : CodeGenerator.getGeneratedPublicFolder();
|
|
836
838
|
const DIST_DIR = `${generatedFolder}/${serviceName}`;
|
|
837
|
-
const DIST_DOCS_DIR = path__default[
|
|
838
|
-
const DIST_DEFINITION_DIR = path__default[
|
|
839
|
+
const DIST_DOCS_DIR = path__default['default'].join(DIST_DIR, "docs");
|
|
840
|
+
const DIST_DEFINITION_DIR = path__default['default'].join(DIST_DIR, "definitions");
|
|
839
841
|
const swaggerFilePath = `${CliParser.getSwaggersOutputPath()}/${swaggerFile}`;
|
|
840
842
|
const swaggerPatchedFilePath = `${CodeGenerator.getPatchedDir()}/${swaggerFile}`;
|
|
841
843
|
const swaggerPatchFilePath = `${swaggerFilePath}patch`;
|
|
@@ -849,25 +851,25 @@ class CodeGenerator {
|
|
|
849
851
|
const { apiBufferByTag, dependenciesByTag, classImports, arrayDefinitions } = CodeGenerator.iterateApi(api);
|
|
850
852
|
const targetSrcFolder = `${CliParser.getOutputPath()}/`;
|
|
851
853
|
for (const tag in apiBufferByTag) {
|
|
852
|
-
const className = ___default[
|
|
854
|
+
const className = ___default['default'].upperFirst(___default['default'].camelCase(tag));
|
|
853
855
|
const apiBuffer = apiBufferByTag[tag];
|
|
854
856
|
const imports = [.../* @__PURE__ */ new Set([...dependenciesByTag[tag], ...Object.values(classImports[className])])];
|
|
855
857
|
const classGenName = CliParser.isAdmin() ? className + "Admin$" : className + "$";
|
|
856
858
|
ParserUtils.writeClassFile(DIST_DIR, classGenName, apiBuffer, imports);
|
|
857
|
-
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default[
|
|
859
|
+
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default['default'].join(DIST_DIR, `${classGenName}`), targetSrcFolder));
|
|
858
860
|
}
|
|
859
861
|
const duplicates = /* @__PURE__ */ new Map();
|
|
860
862
|
for (const ref in api.definitions) {
|
|
861
863
|
const definition = api.definitions[ref];
|
|
862
864
|
let fileName = ParserUtils.parseRefType(ref);
|
|
863
|
-
const fileExist = fs__default[
|
|
865
|
+
const fileExist = fs__default['default'].existsSync(path__default['default'].join(DIST_DEFINITION_DIR, `${fileName}.ts`));
|
|
864
866
|
if (fileExist) {
|
|
865
867
|
fileName = ParserUtils.toCamelCaseWord(ref).replace(".", "").replace(".", "");
|
|
866
868
|
duplicates.set(ref, fileName);
|
|
867
869
|
}
|
|
868
870
|
const { buffer } = new TemplateZod().render(fileName, definition, /* @__PURE__ */ new Map());
|
|
869
871
|
ParserUtils.writeDefinitionFile(DIST_DEFINITION_DIR, fileName, buffer);
|
|
870
|
-
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default[
|
|
872
|
+
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default['default'].join(DIST_DEFINITION_DIR, fileName), targetSrcFolder));
|
|
871
873
|
}
|
|
872
874
|
for (const ref in api.definitions) {
|
|
873
875
|
const definition = api.definitions[ref];
|
|
@@ -875,13 +877,13 @@ class CodeGenerator {
|
|
|
875
877
|
const { buffer, duplicateFound } = new TemplateZod().render(fileName, definition, duplicates);
|
|
876
878
|
if (duplicateFound) {
|
|
877
879
|
ParserUtils.writeDefinitionFile(DIST_DEFINITION_DIR, fileName, buffer);
|
|
878
|
-
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default[
|
|
880
|
+
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default['default'].join(DIST_DEFINITION_DIR, fileName), targetSrcFolder));
|
|
879
881
|
}
|
|
880
882
|
}
|
|
881
883
|
for (const arrayClass of arrayDefinitions) {
|
|
882
884
|
const buffer = new TemplateZodArray().render(arrayClass);
|
|
883
885
|
ParserUtils.writeDefinitionFile(DIST_DEFINITION_DIR, arrayClass, buffer);
|
|
884
|
-
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default[
|
|
886
|
+
indexImportsSet.add(ParserUtils.getRelativePathToWebSdkSrcFolder(path__default['default'].join(DIST_DEFINITION_DIR, arrayClass), targetSrcFolder));
|
|
885
887
|
}
|
|
886
888
|
console.log("\n----------\nCOMPLETED.\n----------\n\n");
|
|
887
889
|
return indexImportsSet;
|
|
@@ -924,7 +926,7 @@ class SwaggerDownloader {
|
|
|
924
926
|
};
|
|
925
927
|
}
|
|
926
928
|
|
|
927
|
-
yargs__default[
|
|
929
|
+
yargs__default['default'].command("download-swaggers", "Download swaggers JSON files", (yargs2) => {
|
|
928
930
|
CliParser.createInstance(yargs2);
|
|
929
931
|
SwaggerDownloader.main();
|
|
930
932
|
}).command("generate-code", "Generate code based on downloaded swagger files", async (yargs2) => {
|
|
@@ -940,7 +942,7 @@ yargs__default["default"].command("download-swaggers", "Download swaggers JSON f
|
|
|
940
942
|
const filenamesSet = /* @__PURE__ */ new Set();
|
|
941
943
|
for (const set of arrayOfSets) {
|
|
942
944
|
set.forEach((value) => {
|
|
943
|
-
const fileName = path__default[
|
|
945
|
+
const fileName = path__default['default'].basename(value);
|
|
944
946
|
if (!filenamesSet.has(fileName)) {
|
|
945
947
|
indexImportsSet.add(value);
|
|
946
948
|
filenamesSet.add(fileName);
|