-
-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
810d607
commit c4f2a55
Showing
17 changed files
with
663 additions
and
0 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
examples/generate-dart-models/__snapshots__/index.spec.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Should be able to render Dart Models and should log expected output to console 1`] = ` | ||
Array [ | ||
"class Root { | ||
Object? email; | ||
Root(); | ||
}", | ||
] | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const spy = jest.spyOn(global.console, 'log').mockImplementation(() => { return; }); | ||
import {generate} from './index'; | ||
|
||
describe('Should be able to render Dart Models', () => { | ||
afterAll(() => { | ||
jest.restoreAllMocks(); | ||
}); | ||
test('and should log expected output to console', async () => { | ||
await generate(); | ||
expect(spy.mock.calls.length).toEqual(2); | ||
expect(spy.mock.calls[1]).toMatchSnapshot(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import {DART_JSON_PRESET, DartGenerator} from '../../src'; | ||
|
||
const generator = new DartGenerator(); | ||
const jsonSchemaDraft7 = { | ||
$schema: 'http://json-schema.org/draft-07/schema#', | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
email: { | ||
type: 'string', | ||
format: 'email' | ||
} | ||
} | ||
};; | ||
|
||
export async function generate() : Promise<void> { | ||
const models = await generator.generate(jsonSchemaDraft7); | ||
for (const model of models) { | ||
console.log(model.result); | ||
} | ||
} | ||
generate(); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"config": { | ||
"example_name": "generate-dart-models" | ||
}, | ||
"scripts": { | ||
"install": "cd ../.. && npm i", | ||
"start": "../../node_modules/.bin/ts-node --cwd ../../ ./examples/$npm_package_config_example_name/index.ts", | ||
"start:windows": "..\\..\\node_modules\\.bin\\ts-node --cwd ..\\..\\ .\\examples\\%npm_package_config_example_name%\\index.ts", | ||
"test": "../../node_modules/.bin/jest --config=../../jest.config.js ./examples/$npm_package_config_example_name/index.spec.ts", | ||
"test:windows": "..\\..\\node_modules\\.bin\\jest --config=..\\..\\jest.config.js examples/%npm_package_config_example_name%/index.spec.ts" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
export const RESERVED_DART_KEYWORDS = [ | ||
'abstract', | ||
'as', | ||
'assert', | ||
'async', | ||
'await', | ||
'break', | ||
'case', | ||
'catch', | ||
'class', | ||
'const', | ||
'continue', | ||
'covariant', | ||
'default', | ||
'deferred', | ||
'do', | ||
'dynamic', | ||
'else', | ||
'enum', | ||
'export', | ||
'extends', | ||
'extension', | ||
'external', | ||
'factory', | ||
'false', | ||
'final', | ||
'for', | ||
'Function', | ||
'get', | ||
'get', | ||
'hide', | ||
'if', | ||
'implements', | ||
'import', | ||
'in', | ||
'interface', | ||
'is', | ||
'late', | ||
'library', | ||
'mixin', | ||
'new', | ||
'null', | ||
'on', | ||
'operator', | ||
'part', | ||
'required', | ||
'rethrow', | ||
'return', | ||
'set', | ||
'show', | ||
'static', | ||
'super', | ||
'switch', | ||
'sync', | ||
'this', | ||
'throw', | ||
'true', | ||
'try', | ||
'typedef', | ||
'var', | ||
'void', | ||
'while', | ||
'with', | ||
'yield', | ||
]; | ||
|
||
export function isReservedDartKeyword(word: string): boolean { | ||
return RESERVED_DART_KEYWORDS.includes(word); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { DartGenerator, DartRenderCompleteModelOptions } from './'; | ||
import { CommonInputModel, OutputModel } from '../../models'; | ||
import * as path from 'path'; | ||
import { AbstractFileGenerator } from '../AbstractFileGenerator'; | ||
import { FileHelpers } from '../../helpers'; | ||
|
||
export class DartFileGenerator extends DartGenerator implements AbstractFileGenerator<DartRenderCompleteModelOptions> { | ||
/** | ||
* Generates all the models to an output directory each model with their own separate files. | ||
* | ||
* @param input | ||
* @param outputDirectory where you want the models generated to | ||
* @param options | ||
*/ | ||
public async generateToFiles(input: Record<string, unknown> | CommonInputModel, outputDirectory: string, options: DartRenderCompleteModelOptions): Promise<OutputModel[]> { | ||
let generatedModels = await this.generateCompleteModels(input, options); | ||
generatedModels = generatedModels.filter((outputModel) => { return outputModel.modelName !== undefined; }); | ||
for (const outputModel of generatedModels) { | ||
const filePath = path.resolve(outputDirectory, `${outputModel.modelName}.dart`); | ||
await FileHelpers.writerToFileSystem(outputModel.result, filePath); | ||
} | ||
return generatedModels; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { | ||
AbstractGenerator, | ||
CommonGeneratorOptions, | ||
defaultGeneratorOptions | ||
} from '../AbstractGenerator'; | ||
import {CommonModel, CommonInputModel, RenderOutput} from '../../models'; | ||
import {CommonNamingConvention, CommonNamingConventionImplementation, ModelKind, TypeHelpers} from '../../helpers'; | ||
import {DartPreset, DART_DEFAULT_PRESET} from './DartPreset'; | ||
import {ClassRenderer} from './renderers/ClassRenderer'; | ||
import {EnumRenderer} from './renderers/EnumRenderer'; | ||
import {isReservedDartKeyword} from './Constants'; | ||
import {Logger} from '../../'; | ||
import {FormatHelpers} from '../../helpers/FormatHelpers'; | ||
|
||
export interface DartOptions extends CommonGeneratorOptions<DartPreset> { | ||
collectionType?: 'List'; | ||
namingConvention?: CommonNamingConvention; | ||
} | ||
|
||
export interface DartRenderCompleteModelOptions { | ||
packageName: string; | ||
} | ||
|
||
export class DartGenerator extends AbstractGenerator<DartOptions, DartRenderCompleteModelOptions> { | ||
static defaultOptions: DartOptions = { | ||
...defaultGeneratorOptions, | ||
defaultPreset: DART_DEFAULT_PRESET, | ||
collectionType: 'List', | ||
namingConvention: CommonNamingConventionImplementation | ||
}; | ||
|
||
constructor( | ||
options: DartOptions = DartGenerator.defaultOptions, | ||
) { | ||
super('Dart', DartGenerator.defaultOptions, options); | ||
} | ||
|
||
/** | ||
* Render a scattered model, where the source code and library and model dependencies are separated. | ||
* | ||
* @param model | ||
* @param inputModel | ||
*/ | ||
render(model: CommonModel, inputModel: CommonInputModel): Promise<RenderOutput> { | ||
const kind = TypeHelpers.extractKind(model); | ||
// We don't support union in Dart generator, however, if union is an object, we render it as a class. | ||
if (kind === ModelKind.OBJECT || (kind === ModelKind.UNION && model.type?.includes('object'))) { | ||
return this.renderClass(model, inputModel); | ||
} else if (kind === ModelKind.ENUM) { | ||
return this.renderEnum(model, inputModel); | ||
} | ||
Logger.warn(`Dart generator, cannot generate this type of model, ${model.$id}`); | ||
return Promise.resolve(RenderOutput.toRenderOutput({result: '', renderedName: '', dependencies: []})); | ||
} | ||
|
||
/** | ||
* Render a complete model result where the model code, library and model dependencies are all bundled appropriately. | ||
* | ||
* For Dart you need to specify which package the model is placed under. | ||
* | ||
* @param model | ||
* @param inputModel | ||
* @param options used to render the full output | ||
*/ | ||
async renderCompleteModel(model: CommonModel, inputModel: CommonInputModel, options: DartRenderCompleteModelOptions): Promise<RenderOutput> { | ||
if (isReservedDartKeyword(options.packageName)) { | ||
throw new Error(`You cannot use reserved Dart keyword (${options.packageName}) as package name, please use another.`); | ||
} | ||
|
||
const outputModel = await this.render(model, inputModel); | ||
const modelDependencies = model.getNearestDependencies().map((dependencyModelName) => { | ||
const formattedDependencyModelName = this.options.namingConvention?.type ? this.options.namingConvention.type(dependencyModelName, { | ||
inputModel, | ||
model: inputModel.models[String(dependencyModelName)], | ||
reservedKeywordCallback: isReservedDartKeyword | ||
}) : dependencyModelName; | ||
return `import 'package:${options.packageName}/${FormatHelpers.snakeCase(formattedDependencyModelName)}.dart';`; | ||
}); | ||
const outputContent = `${modelDependencies.join('\n')} | ||
${outputModel.dependencies.join('\n')} | ||
${outputModel.result}`; | ||
return RenderOutput.toRenderOutput({ | ||
result: outputContent, | ||
renderedName: outputModel.renderedName, | ||
dependencies: outputModel.dependencies | ||
}); | ||
} | ||
|
||
async renderClass(model: CommonModel, inputModel: CommonInputModel): Promise<RenderOutput> { | ||
const presets = this.getPresets('class'); | ||
const renderer = new ClassRenderer(this.options, this, presets, model, inputModel); | ||
const result = await renderer.runSelfPreset(); | ||
const renderedName = FormatHelpers.snakeCase(renderer.nameType(model.$id, model)); | ||
return RenderOutput.toRenderOutput({result, renderedName, dependencies: renderer.dependencies}); | ||
} | ||
|
||
async renderEnum(model: CommonModel, inputModel: CommonInputModel): Promise<RenderOutput> { | ||
const presets = this.getPresets('enum'); | ||
const renderer = new EnumRenderer(this.options, this, presets, model, inputModel); | ||
const result = await renderer.runSelfPreset(); | ||
const renderedName = FormatHelpers.snakeCase(renderer.nameType(model.$id, model)); | ||
return RenderOutput.toRenderOutput({result, renderedName, dependencies: renderer.dependencies}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Preset, ClassPreset, EnumPreset } from '../../models'; | ||
import { ClassRenderer, DART_DEFAULT_CLASS_PRESET } from './renderers/ClassRenderer'; | ||
import { EnumRenderer, DART_DEFAULT_ENUM_PRESET } from './renderers/EnumRenderer'; | ||
|
||
export type DartPreset = Preset<{ | ||
class: ClassPreset<ClassRenderer>; | ||
enum: EnumPreset<EnumRenderer>; | ||
}>; | ||
|
||
export const DART_DEFAULT_PRESET: DartPreset = { | ||
class: DART_DEFAULT_CLASS_PRESET, | ||
enum: DART_DEFAULT_ENUM_PRESET, | ||
}; |
Oops, something went wrong.