Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: union type sorting and various dependency issues #1

Merged
merged 5 commits into from
May 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
"indent": [
"error",
4
]
],
"unicorn/consistent-function-scoping": "off",
"unicorn/no-array-callback-reference": "off"
},
"extends": [
"oclif",
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,3 @@ const stringContent = new CFDefinitionsBuilder()
### Browser Usage
You can use `CFDefinitionsBuilder` also in a browser environment.
> Example: [TS Content Types Generator App](https://github.com/marcolink/cf-content-types-generator-app)

24 changes: 13 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"@oclif/errors": "latest",
"@oclif/plugin-help": "^3",
"cli-ux": "^5.5.1",
"contentful": "^8.1.7",
"contentful-export": "^7.11.6",
"contentful": "^9.1.28",
"contentful-export": "^7.16.0",
"fs-extra": "^9.1.0",
"lodash": "^4.17.15",
"ts-morph": "9.1.0",
Expand All @@ -38,18 +38,15 @@
"@oclif/dev-cli": "^1",
"@oclif/test": "^1.2.5",
"@semantic-release/changelog": "^5.0.1",
"@types/chai": "^4",
"@types/fs-extra": "^9.0.1",
"@types/lodash": "^4.14.155",
"@types/mocha": "^8",
"chai": "^4",
"eslint": "^7.12",
"eslint-config-oclif": "^3.1",
"eslint-config-oclif-typescript": "^0.2",
"@typescript-eslint/eslint-plugin": "^5.22.0",
"eslint": "^8.14.0",
"eslint-config-oclif": "^4.0.0",
"eslint-config-oclif-typescript": "^1.0.2",
"eslint-plugin-unicorn": "^42.0.0",
"jest-fixtures": "^0.6.0",
"mocha": "^5",
"nyc": "^15",
"semantic-release": "^17.0.7",
"semantic-release": "^19.0.2",
"strip-indent": "^3.0.0",
"typescript": "4.2.2"
},
Expand Down Expand Up @@ -90,6 +87,11 @@
"@semantic-release/github"
]
},
"resolutions": {
"ansi-regex": ">=3.0.1 <6.0.0",
"minimist": ">=1.2.6",
"path-parse": ">=1.0.7"
},
"publishConfig": {
"registry": "https://npm.pkg.github.com/xeroxinteractive"
}
Expand Down
51 changes: 25 additions & 26 deletions src/cf-definitions-builder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Field} from 'contentful';
import * as path from 'path';
import * as path from 'node:path';
import {
forEachStructureChild,
ImportDeclarationStructure,
Expand Down Expand Up @@ -52,7 +52,7 @@ export default class CFDefinitionsBuilder {

const interfaceDeclaration = this.createInterfaceDeclaration(file, moduleFieldsName(model.sys.id));

model.fields.forEach(field => this.addProperty(file, interfaceDeclaration, field));
for (const field of model.fields) this.addProperty(file, interfaceDeclaration, field);

this.addEntryTypeAlias(file, model.sys.id, moduleFieldsName(model.sys.id));

Expand Down Expand Up @@ -81,34 +81,33 @@ export default class CFDefinitionsBuilder {
const imports: OptionalKind<ImportDeclarationStructure>[] = [];
const types: string[] = [];

this.project.getSourceFiles()
.filter(sourceFile => sourceFile.getBaseNameWithoutExtension() !== mergeFileName)
.forEach(sourceFile => forEachStructureChild(sourceFile.getStructure(),
childStructure => {
switch (childStructure.kind) {
case StructureKind.ImportDeclaration:
imports.push(childStructure);
break;
case StructureKind.Interface:
types.push(childStructure.name);
mergeFile.addInterface(childStructure);
break;
case StructureKind.TypeAlias:
types.push(childStructure.name);
mergeFile.addTypeAlias(childStructure);
break;
default:
throw new Error(`Unhandled node type '${StructureKind[childStructure.kind]}'.`);
}
}));
for (const sourceFile of this.project.getSourceFiles()
.filter(sourceFile => sourceFile.getBaseNameWithoutExtension() !== mergeFileName)) forEachStructureChild(sourceFile.getStructure(),
childStructure => {
switch (childStructure.kind) {
case StructureKind.ImportDeclaration:
imports.push(childStructure);
break;
case StructureKind.Interface:
types.push(childStructure.name);
mergeFile.addInterface(childStructure);
break;
case StructureKind.TypeAlias:
types.push(childStructure.name);
mergeFile.addTypeAlias(childStructure);
break;
default:
throw new Error(`Unhandled node type '${StructureKind[childStructure.kind]}'.`);
}
});

// only import modules not present in merge file
imports.forEach(importD => {
for (const importD of imports) {
const name = importD.moduleSpecifier.slice(2);
if (!types.includes(name)) {
mergeFile.addImportDeclaration(importD);
}
});
}

mergeFile.organizeImports({
ensureNewLineAtEndOfFile: true,
Expand Down Expand Up @@ -154,7 +153,7 @@ export default class CFDefinitionsBuilder {
namedImports: ['CMSManagementEntry'],
});

files.forEach(fileName => {
for (const fileName of files) {
indexFile.addImportDeclaration({
isTypeOnly: true,
namedImports: [moduleName(fileName), moduleFieldsName(fileName)],
Expand All @@ -169,7 +168,7 @@ export default class CFDefinitionsBuilder {
moduleSpecifier: `./${fileName}`,
});
cmsEntries.push(moduleName(fileName));
});
}

indexFile.addTypeAlias({isExported: true, name: 'CMSEntries', type: renderUnionType(cmsEntries)});
indexFile.addTypeAlias({isExported: true, name: 'CMSManagementEntries', type: renderUnionType(cmsEntries.map(name => renderGenericType('CMSManagementEntry', name)))});
Expand Down
2 changes: 2 additions & 0 deletions src/cf-property-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ export const propertyImports = (field: Field, ignoreModule?: string): OptionalKi
.filter(filterIgnoredModule)
.map(moduleImport) : [{moduleSpecifier: './index', namedImports: ['CMSEntries']}];
}

if (field.type === 'Array' && field.items) {
return field.items?.validations?.length > 0 ? linkContentTypeValidations(field.items)
.filter(filterIgnoredModule)
.map(moduleImport) : [{moduleSpecifier: './index', namedImports: ['CMSEntries']}];
}

return [];
};
2 changes: 2 additions & 0 deletions src/cf-property-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ export const anyType = (field: Field): string => {
) {
return renderLiteralType;
}

return (value: string) => value.toString();
};

return renderUnionType(includesValidation.in.map(mapper()));
}
}
Expand Down
9 changes: 8 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import {Command, flags} from '@oclif/command';
import * as fs from 'fs-extra';
import {writeFile} from 'fs-extra';
import * as path from 'path';
import * as path from 'node:path';
import CFDefinitionsBuilder from './cf-definitions-builder';

// Does not appear to work as an import, not sure why and I'm just clearing up the audit
// quickly so don't want to spent time messing about if it works.
// eslint-disable-next-line unicorn/prefer-module
const contentfulExport = require('contentful-export');

class ContentfulMdg extends Command {
Expand Down Expand Up @@ -43,6 +46,7 @@ class ContentfulMdg extends Command {
spaceId: flags.spaceId,
managementToken: flags.token,
environmentId: flags.environment,
// https://github.com/contentful/contentful-export/issues/966
skipEditorInterfaces: true,
skipContent: true,
skipRoles: true,
Expand All @@ -52,13 +56,16 @@ class ContentfulMdg extends Command {
}

const builder = new CFDefinitionsBuilder();

// eslint-disable-next-line unicorn/no-array-for-each
content.contentTypes.forEach(builder.appendType);

if (flags.out) {
const outDir = path.resolve(flags.out);
if (!flags.preserve && fs.existsSync(outDir)) {
await fs.remove(outDir);
}

await fs.ensureDir(outDir);
await builder.write(flags.out, writeFile);
} else {
Expand Down
1 change: 1 addition & 0 deletions src/renderer/cf-render-prop-array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const renderPropArray = (field: Field): string => {
if (validation?.length > 0) {
return `(${renderUnionType(validation.map(renderLiteralType))})[]`;
}

return 'Contentful.EntryFields.Symbol[]';
}

Expand Down
2 changes: 2 additions & 0 deletions src/renderer/cf-render-prop-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ export const renderPropLink = (field: Pick<Field, 'validations' | 'linkType'>) =
if (field.linkType === 'Entry') {
return linkContentType(field);
}

if (field.linkType === 'Asset') {
return 'AssetLink';
}

return 'Contentful.' + field.linkType!;
};
2 changes: 1 addition & 1 deletion src/renderer/render-union-type.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const renderUnionType = (types: string[]): string => types.join(' | ');
export const renderUnionType = (types: string[]): string => types.sort().join(' | ');
3 changes: 2 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ export const moduleTypeIdName = (name: string): string => camelCase(moduleName(n
type WithValidations = Pick<FieldItem, 'validations'>;

const validation = (node: WithValidations, field: keyof FieldValidation): any => {
if (node.validations && node.validations.length !== 0) {
if (node.validations && node.validations.length > 0) {
const linkContentValidation = node.validations.find(value => value[field]);
if (linkContentValidation) {
return linkContentValidation[field] || [];
}
}

return [];
};

Expand Down
Loading