Skip to content

Commit 93a2111

Browse files
committed
now works for components
1 parent a238338 commit 93a2111

11 files changed

+101
-63
lines changed

bin/index.js

100644100755
File mode changed.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
},
88
"scripts": {
99
"build": "tsc -p .",
10+
"testtypes": "node ./bin/index.js --out src/testtypes",
1011
"t4s": "node ./bin/index.js"
1112
},
1213
"repository": {

src/interface/Attributes.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ export default class Attributes {
1515
case "component":
1616
case "dynamiczone":
1717
case "relation":
18-
return false;
18+
return true;
1919
default:
2020
break;
2121
}
2222

23-
return attr.required !== true;
23+
return !attr.required;
2424
}
2525

26-
getDependencies() {
26+
getDependencies(strapiName: string) {
2727
const dependencies = [];
2828
for (const attrName in this.Attrs) {
2929
const attr = this.Attrs[attrName];
@@ -38,18 +38,24 @@ export default class Attributes {
3838
default:
3939
continue;
4040
}
41+
// // If the current dependency is the interface itself, do not report it as a dependency
42+
// if (dependencyName === strapiName) {
43+
// continue;
44+
// }
4145
dependencies.push(dependencyName);
4246
}
4347
return dependencies;
4448
}
4549

4650
attributeToString(attrName: string, attr: any) {
4751
let optionalString = this.isAttributeOptional(attr) ? '?' : '';
48-
let str = `${attrName}${optionalString}: `
52+
let str = ` ${attrName}${optionalString}: `
4953
let isArray : boolean = false;
5054
switch (attr.type) {
5155
case "relation":
5256
const apiName = attr.target;
57+
// console.log(attrName)
58+
// console.log(this.RelationNames, apiName)
5359
const dependencyName = this.RelationNames[apiName][0];
5460
isArray = attr.relation.endsWith("ToMany");
5561
str += dependencyName;
@@ -82,6 +88,7 @@ export default class Attributes {
8288
break;
8389
case "boolean":
8490
str += attr.type;
91+
break;
8592
case "json":
8693
default:
8794
str += "any";
@@ -102,7 +109,7 @@ export default class Attributes {
102109
}
103110
strings.push(attrString)
104111
}
105-
strings.push("}")
112+
strings.push(" }")
106113
return strings.join("\n");
107114
}
108115
}

src/interface/ComponentInterface.ts

+11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1+
import { prefixDotSlash } from "../utils";
12
import Interface from "./Interface";
23

34
export default class ComponentInterface extends Interface {
5+
protected Category: string;
46

7+
constructor(baseName: string, attributes: any, relativeDirectoryPath: string, category: string, prefix: string = "") {
8+
super(baseName, attributes, relativeDirectoryPath, prefix);
9+
this.Category = category;
10+
this.updateStrapiName();
11+
}
12+
13+
updateStrapiName() {
14+
this.StrapiName = `${this.Category}.${this.getBaseName()}`
15+
}
516
}

src/interface/Interface.ts

+41-27
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
1-
import { join, parse, relative } from "path";
1+
import { dirname, join, parse, relative } from "path";
2+
import { pascalCase, prefixDotSlash } from "../utils";
23
import Attributes from "./Attributes";
34

45
export default class Interface {
5-
private BaseName: string;
6+
protected BaseName: string;
67
private Relations: Interface[] = []; // Components and relations
78
private RelationNames: Record<string, [string, Interface]> = {};
89
private RelationNamesCounter: Record<string, number> = {};
910
private NamePrefix: string = "";
1011
private Attributes: any;
1112
private RelativeDirectoryPath: string;
12-
private StrapiName: string;
13+
protected StrapiName: string;
1314

1415
constructor(baseName: string, attributes: any, relativeDirectoryPath: string, prefix: string = "") {
1516
this.BaseName = baseName;
16-
this.StrapiName = `api::${baseName}.${baseName}`;
17+
this.updateStrapiName()
1718
this.NamePrefix = prefix;
1819
this.Attributes = attributes;
1920
this.RelativeDirectoryPath = relativeDirectoryPath;
2021
}
2122

23+
protected updateStrapiName() {
24+
this.StrapiName = `api::${this.BaseName}.${this.BaseName}`;
25+
}
26+
2227
getBaseName() {
2328
return this.BaseName;
2429
}
@@ -29,18 +34,23 @@ export default class Interface {
2934

3035
getDependencies() {
3136
const attrs = new Attributes(this.Attributes, this.RelationNames);
32-
return attrs.getDependencies();
37+
return attrs.getDependencies(this.getStrapiName());
3338
}
3439

3540
getFullInterfaceName() {
36-
return `${this.NamePrefix}${this.BaseName}`;
41+
const pascalName = pascalCase(this.BaseName);
42+
return `${this.NamePrefix}${pascalName}`;
3743
}
3844

3945
// For typescript import from index file
4046
getRelativeRootPath() {
4147
const path = join(this.RelativeDirectoryPath, this.getBaseName());
42-
const relativePath = (/^\.?\.\//).test(path) ? path : "./" + path;
43-
return relativePath;
48+
return prefixDotSlash(path);
49+
}
50+
51+
getRelativeRootDir() {
52+
const path = dirname(this.getRelativeRootPathFile());
53+
return path;
4454
}
4555

4656
getRelativeRootPathFile() {
@@ -51,55 +61,59 @@ export default class Interface {
5161
this.Relations = relations;
5262
this.RelationNames = {};
5363
this.Relations.forEach((inter: Interface) => {
54-
let name = inter.getBaseName();
55-
// Avoid duplicate names
56-
if (name in this.RelationNamesCounter) {
57-
name += ++this.RelationNamesCounter[name];
64+
let name = inter.getFullInterfaceName();
65+
// FIXME: clean up this mess...
66+
if (inter.getStrapiName() === this.getStrapiName()) {
5867
} else {
59-
this.RelationNamesCounter[name] = 0;
68+
// Avoid duplicate names
69+
if (name in this.RelationNamesCounter) {
70+
name += ++this.RelationNamesCounter[name];
71+
} else {
72+
this.RelationNamesCounter[name] = 0;
73+
}
6074
}
6175
this.RelationNames[inter.getStrapiName()] = [name, inter];
6276
})
6377
}
6478

6579
private getTsImports() {
6680
return Object.keys(this.RelationNames).map((strapiName: string) => {
81+
if (strapiName === this.getStrapiName()) {
82+
return "";
83+
}
6784
const relationName = this.RelationNames[strapiName][0];
6885
const inter = this.RelationNames[strapiName][1];
69-
const importPath = relative(this.getRelativeRootPath(), inter.getRelativeRootPath());
86+
const importPath = prefixDotSlash(relative(this.getRelativeRootDir(), inter.getRelativeRootPath()));
7087
const fullName = inter.getFullInterfaceName();
7188
const importNameString = fullName === relationName ? fullName : `${fullName} as ${relationName}`;
7289
return `import { ${importNameString} } from '${importPath}';`;
73-
}).join("\n");
90+
}).filter(s => s).join("\n");
7491
}
7592

7693
attributesToString() {
77-
let str = '';
78-
for (const attributeName in this.Attributes) {
79-
const attr = this.Attributes[attributeName];
80-
switch (attr.type) {
81-
default:
82-
83-
break;
84-
}
85-
}
94+
const attrs = new Attributes(this.Attributes, this.RelationNames);
95+
return attrs.toString();
8696
}
8797

8898
getInerfaceString() {
89-
let str = 'export interface ${this.getFullInterfaceName()} {\n';
99+
let str = `export interface ${this.getFullInterfaceName()} {\n`;
90100
str += this.getInterfaceFieldsString();
91101
str += `}`
92102
return str;
93103
}
94104

95105
getInterfaceFieldsString() {
96-
let str: string;
106+
let str = '';
97107
str += ` id: number;\n`;
98108
str += ` attributes: ${this.attributesToString()}\n`;
99109
return str;
100110
}
101111

102112
toString() {
103-
return this.getTsImports() + this.getInerfaceString();
113+
const strings = [
114+
this.getTsImports(),
115+
this.getInerfaceString()
116+
];
117+
return strings.join("\n")
104118
}
105119
}

src/interface/InterfaceManager.ts

+19-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { existsSync } from "fs";
12
import { mkdir, rm, writeFile } from "fs/promises";
23
import { join } from "path";
4+
import { pascalCase } from "../utils";
5+
import ComponentInterface from "./ComponentInterface";
36
import Interface from "./Interface";
47
import { getApiSchemas, getComponentCategoryFolders, getComponentSchemas } from "./schemaReader";
58

@@ -39,20 +42,22 @@ export default class InterfaceManager {
3942
category.schemas.forEach((schema) => {
4043
const componentName = schema.name;
4144
const strapiName = `${categoryName}.${schema.name}`
42-
const componentPrefix = `${this.Options.componentPrefix}${this.Options.useCategoryPrefix ? categoryName : ""}`;
45+
const componentPrefix = `${this.Options.componentPrefix}${this.Options.useCategoryPrefix ? pascalCase(categoryName) : ""}`;
4346
const prefix = this.Options.componentPrefixOverridesPrefix ? componentPrefix : this.Options.prefix + componentPrefix;
4447
// TODO: make component interface
45-
// const inter = new Interface(componentName, schema.attributes, `./${categoryName}`, prefix);
46-
// this.Interfaces[strapiName] = inter;
48+
const inter = new ComponentInterface(componentName, schema.attributes, `./${categoryName}`, categoryName, prefix);
49+
this.Interfaces[strapiName] = inter;
4750
})
4851
})
4952
}
5053

5154
// Inject dependencies into all interfaces
5255
injectDependencies() {
56+
// console.log("Injecting dependencies")
5357
Object.keys(this.Interfaces).forEach((strapiName: string) => {
5458
const inter = this.Interfaces[strapiName];
5559
const dependencies = inter.getDependencies();
60+
// console.log(`Interfaces for ${inter.getStrapiName()} are`)
5661
const interfacesToInject = dependencies.map((dependencyStrapiName: string) => {
5762
return this.Interfaces[dependencyStrapiName];
5863
}).filter((inter) => inter);
@@ -62,22 +67,25 @@ export default class InterfaceManager {
6267

6368
async makeFolders() {
6469
const componentCategories = await getComponentCategoryFolders(this.StrapiSrcRoot);
65-
await rm(this.OutRoot, {
66-
recursive: true,
67-
});
68-
await mkdir(this.OutRoot, {
69-
recursive: true,
70-
});
70+
if (!existsSync(this.OutRoot)) {
71+
await mkdir(this.OutRoot, {
72+
recursive: true,
73+
});
74+
}
7175
await Promise.all(componentCategories.map(async (category) => {
72-
await mkdir(join(this.OutRoot, category));
76+
const path = join(this.OutRoot, category);
77+
if (existsSync(path)) {
78+
return;
79+
}
80+
await mkdir(path);
7381
}));
7482
}
7583

7684
async writeInterfaces() {
7785
const writePromises = Object.keys(this.Interfaces).map(async (strapiName) => {
7886
const inter = this.Interfaces[strapiName];
7987
const fileData = inter.toString();
80-
const filePath = join(this.OutRoot, inter.getRelativeRootPath());
88+
const filePath = join(this.OutRoot, inter.getRelativeRootPathFile());
8189
await writeFile(filePath, fileData)
8290
});
8391
await Promise.all(writePromises);

src/interface/schemaReader.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ export async function getComponentSchemas(strapiSrcRoot: string) {
2727
const schemaFilesPath = join(strapiSrcRoot, "components", category);
2828
const schemaFiles = await readDirFiltered(schemaFilesPath);
2929
const schemaNamesWithAttributesPromises = schemaFiles.map(async (file: string) => {
30-
const attributes = await readSchema(file);
30+
const schemaPath = join(schemaFilesPath, file);
31+
const attributes = await readSchema(schemaPath);
3132
const name = file.split(".")[0];
3233
return { name, attributes }
3334
})

src/utils/index.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import { readdir } from "fs/promises";
22

3-
export function strapiToPascalCase(strapiName: string) {
4-
3+
export function pascalCase(name: string) {
4+
const words = name.match(/[a-z]+/gi);
5+
const pascalName = words.map((word: string) => {
6+
return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();
7+
}).join("");
8+
// console.log(pascalName)
9+
return pascalName;
510
}
611

712
export async function readDirFiltered(dir: string) {
813
const folders = await readdir(dir);
914
return folders.filter((folder: string) => !folder.startsWith("."));
1015
}
16+
17+
export function prefixDotSlash(path) {
18+
return (/^\.?\.\//).test(path) ? path : "./" + path;
19+
}

tsconfig.json

-14
This file was deleted.

tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tsconfig.jsonc

tsconfig.jsonc

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
"module": "commonjs", /* 'none', 'commonjs', 'amd', 'system', etc */
66
"declaration": true, /* Concatenate & emit output to single file.*/
77
"outDir": "lib", /* Redirect output to the directory. */
8-
"rootDir": "src",
98
"types": [ "node" ],
109
"resolveJsonModule": true,
1110
"esModuleInterop": true, /* Enables intero between CommonJS and ES */
1211
"skipLibCheck": true /* Skip type checking of declaration files. */
13-
}
12+
},
13+
"include": [ "src/**/*" ],
14+
"exclude": [ "types/**/*", "src/testtypes/**/*" ]
1415
}

tsconfig.tsbuildinfo

-1
This file was deleted.

0 commit comments

Comments
 (0)