rebase to upstream master

This commit is contained in:
Milton Howe 2018-01-15 15:13:28 -05:00
parent 42231ce376
commit f3458dbbe8
39 changed files with 3553 additions and 1306 deletions

9
.idea/codeStyleSettings.xml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value />
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</component>
</project>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

6
.idea/encodings.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/entity.mst" charset="UTF-8" />
</component>
</project>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="TsLint" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>

4
.idea/jsLinters/tslint.xml generated Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="TsLintConfiguration" use-custom-config-file="true" custom-config-file-path="$PROJECT_DIR$/tslint.json" />
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/typeorm-model-generator.iml" filepath="$PROJECT_DIR$/.idea/typeorm-model-generator.iml" />
</modules>
</component>
</project>

12
.idea/typeorm-model-generator.iml generated Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

837
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,837 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="553b0e84-f94c-421c-926f-494eed61c10c" name="Default" comment="">
<change beforePath="" afterPath="$PROJECT_DIR$/test/integration/entityTypes.test.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/test/integration/entityTypes/mariadb/entity/Post.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/test/integration/entityTypes/mssql/entity/Post.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/test/integration/entityTypes/mysql/entity/Post.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/test/integration/entityTypes/postgres/entity/Post.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/test/integration/github-issues/12/entity/Post.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/test/integration/github-issues/12/entity/PostAuthor.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/test/integration/githubIssues.test.ts" />
<change beforePath="" afterPath="$PROJECT_DIR$/test/utils/GeneralTestUtils.ts" />
<change beforePath="$PROJECT_DIR$/.travis.yml" afterPath="$PROJECT_DIR$/.travis.yml" />
<change beforePath="$PROJECT_DIR$/README.md" afterPath="$PROJECT_DIR$/README.md" />
<change beforePath="$PROJECT_DIR$/docker-compose.yml" afterPath="$PROJECT_DIR$/docker-compose.yml" />
<change beforePath="$PROJECT_DIR$/package-lock.json" afterPath="$PROJECT_DIR$/package-lock.json" />
<change beforePath="$PROJECT_DIR$/package.json" afterPath="$PROJECT_DIR$/package.json" />
<change beforePath="$PROJECT_DIR$/src/Engine.ts" afterPath="$PROJECT_DIR$/src/Engine.ts" />
<change beforePath="$PROJECT_DIR$/src/drivers/AbstractDriver.ts" afterPath="$PROJECT_DIR$/src/drivers/AbstractDriver.ts" />
<change beforePath="$PROJECT_DIR$/src/drivers/MariaDbDriver.ts" afterPath="$PROJECT_DIR$/src/drivers/MariaDbDriver.ts" />
<change beforePath="$PROJECT_DIR$/src/drivers/MssqlDriver.ts" afterPath="$PROJECT_DIR$/src/drivers/MssqlDriver.ts" />
<change beforePath="$PROJECT_DIR$/src/drivers/MysqlDriver.ts" afterPath="$PROJECT_DIR$/src/drivers/MysqlDriver.ts" />
<change beforePath="$PROJECT_DIR$/src/drivers/PostgresDriver.ts" afterPath="$PROJECT_DIR$/src/drivers/PostgresDriver.ts" />
<change beforePath="$PROJECT_DIR$/src/entity.mst" afterPath="$PROJECT_DIR$/src/entity.mst" />
<change beforePath="$PROJECT_DIR$/src/index.ts" afterPath="$PROJECT_DIR$/src/index.ts" />
<change beforePath="$PROJECT_DIR$/src/models/ColumnInfo.ts" afterPath="$PROJECT_DIR$/src/models/ColumnInfo.ts" />
<change beforePath="$PROJECT_DIR$/test/drivers/MssqlDriver.test.ts" afterPath="$PROJECT_DIR$/test/drivers/MssqlDriver.test.ts" />
<change beforePath="$PROJECT_DIR$/test/integration/examples/sample1-simple-entity/entity/Post.ts" afterPath="$PROJECT_DIR$/test/integration/examples/sample1-simple-entity/entity/Post.ts" />
<change beforePath="$PROJECT_DIR$/test/integration/examples/sample11-all-types-entity/entity/EverythingEntity.ts" afterPath="$PROJECT_DIR$/test/integration/examples/sample11-all-types-entity/entity/EverythingEntity.ts" />
<change beforePath="$PROJECT_DIR$/test/integration/integration.test.ts" afterPath="$PROJECT_DIR$/test/integration/integration.test.ts" />
<change beforePath="$PROJECT_DIR$/test/utils/EntityFileToJson.ts" afterPath="$PROJECT_DIR$/test/utils/EntityFileToJson.ts" />
<change beforePath="$PROJECT_DIR$/tsconfig.json" afterPath="$PROJECT_DIR$/tsconfig.json" />
<change beforePath="$PROJECT_DIR$/typings.json" afterPath="$PROJECT_DIR$/typings.json" />
</list>
<ignored path="$PROJECT_DIR$/.tmp/" />
<ignored path="$PROJECT_DIR$/temp/" />
<ignored path="$PROJECT_DIR$/tmp/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="450">
<file leaf-file-name="Engine.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Engine.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="233">
<caret line="37" column="23" lean-forward="false" selection-start-line="37" selection-start-column="23" selection-end-line="37" selection-end-column="23" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="docker-compose.yml" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/docker-compose.yml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="403">
<caret line="13" column="10" lean-forward="false" selection-start-line="13" selection-start-column="10" selection-end-line="13" selection-end-column="10" />
<folding>
<marker date="1516041617309" expanded="true" signature="13:786" ph="services: &lt;4 keys&gt;" />
<marker date="1516041617309" expanded="true" signature="54:66" ph="mysql:5.7.10" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="index.js" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/dist/src/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="992">
<caret line="32" column="44" lean-forward="false" selection-start-line="32" selection-start-column="44" selection-end-line="32" selection-end-column="44" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="entity.mst" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/entity.mst">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="713">
<caret line="23" column="17" lean-forward="false" selection-start-line="23" selection-start-column="17" selection-end-line="23" selection-end-column="17" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="package.json" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="527">
<caret line="35" column="18" lean-forward="false" selection-start-line="35" selection-start-column="18" selection-end-line="35" selection-end-column="18" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="MysqlDriver.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/drivers/MysqlDriver.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="545">
<caret line="68" column="30" lean-forward="false" selection-start-line="68" selection-start-column="30" selection-end-line="68" selection-end-column="30" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="ColumnInfo.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/models/ColumnInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="155">
<caret line="5" column="25" lean-forward="false" selection-start-line="5" selection-start-column="25" selection-end-line="5" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="index.ts" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/index.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1178">
<caret line="45" column="53" lean-forward="false" selection-start-line="45" selection-start-column="53" selection-end-line="45" selection-end-column="53" />
<folding>
<element signature="e#0#58#0" expanded="true" />
<marker date="1516041800196" expanded="true" signature="2862:2898" ph="{&quot;host&quot;: argv.h...}" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>char_max_lenght</find>
<find>.mst</find>
<find>EntityName</find>
<find>lower</find>
<find>relationimports</find>
<find>relatedTable</find>
<find>imports</find>
<find>relations</find>
<find>ownertable</find>
<find>Handlebars</find>
<find>toLowerCase</find>
<find>changeCase</find>
<find>changeCase.param</find>
<find>relationImports</find>
<find>char</find>
<find>argv</find>
<find>engineoptions</find>
<find>convertCase</find>
<find>camelcase</find>
<find>sample1-s</find>
<find>integration.test</find>
<find>&quot;boolean&quot;</find>
<find>&quot;bool&quot;</find>
<find>bool</find>
</findStrings>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/tslint.json" />
<option value="$PROJECT_DIR$/src/models/DatabaseModel.ts" />
<option value="$PROJECT_DIR$/dist/src/Engine.js" />
<option value="$PROJECT_DIR$/src/models/RelationInfo.ts" />
<option value="$PROJECT_DIR$/tsconfig.json" />
<option value="$PROJECT_DIR$/src/Engine.js" />
<option value="$PROJECT_DIR$/test/integration/integration.test.ts" />
<option value="$PROJECT_DIR$/src/models/EntityInfo.ts" />
<option value="$PROJECT_DIR$/src/index.ts" />
<option value="$PROJECT_DIR$/docker-compose.yml" />
<option value="$PROJECT_DIR$/README.md" />
<option value="$PROJECT_DIR$/src/models/ColumnInfo.ts" />
<option value="$PROJECT_DIR$/src/drivers/MysqlDriver.ts" />
<option value="$PROJECT_DIR$/src/entity.mst" />
<option value="$PROJECT_DIR$/src/Engine.ts" />
<option value="$PROJECT_DIR$/package.json" />
</list>
</option>
</component>
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER">
<package-json value="$PROJECT_DIR$/package.json" />
</component>
<component name="JsGulpfileManager">
<detection-done>true</detection-done>
<sorting>DEFINITION_ORDER</sorting>
</component>
<component name="NodeModulesDirectoryManager">
<handled-path value="$PROJECT_DIR$/node_modules" />
</component>
<component name="PackageJsonUpdateNotifier">
<dismissed value="$PROJECT_DIR$/package.json" />
</component>
<component name="ProjectFrameBounds">
<option name="x" value="-3191" />
<option name="y" value="43" />
<option name="width" value="2661" />
<option name="height" value="1538" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
<manualOrder />
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="typeorm-model-generator" type="b2602c69:ProjectViewProjectNode" />
<item name="typeorm-model-generator" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="typeorm-model-generator" type="b2602c69:ProjectViewProjectNode" />
<item name="typeorm-model-generator" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
<pane id="Scratches" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="settings.editor.selected.configurable" value="reference.settingsdialog.IDE.editor.colors.Handlebars/Mustache" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="nodejs_interpreter_path" value="C:/Program Files/nodejs/node" />
<property name="node.js.selected.package.tslint" value="C:\Users\milton\workspace\typeorm-model-generator\node_modules\tslint" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/node_modules/tslint" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="typescript-compiler-editor-notification" value="false" />
<property name="HbShouldOpenHtmlAsHb" value="" />
<property name="add_unversioned_files" value="$PROJECT_DIR$/src/Engine.js" />
<property name="SearchEverywhereHistoryKey" value="package&#9;FILE&#9;file://C:/Users/milton/workspace/typeorm-model-generator/package.json&#10;read&#9;FILE&#9;file://C:/Users/milton/workspace/typeorm-model-generator/README.md" />
<property name="nodejs.mocha.mocha_node_package_dir" value="$PROJECT_DIR$/node_modules/mocha" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\milton\workspace\typeorm-model-generator" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="ShelveChangesManager" show_recycled="false">
<option name="remove_strategy" value="false" />
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="553b0e84-f94c-421c-926f-494eed61c10c" name="Default" comment="" />
<created>1505146396007</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1505146396007</updated>
<workItem from="1505146397562" duration="18392000" />
<workItem from="1505224609754" duration="7274000" />
<workItem from="1505231918547" duration="9090000" />
<workItem from="1505391036478" duration="80000" />
<workItem from="1505391261167" duration="5581000" />
<workItem from="1506111401255" duration="1363000" />
<workItem from="1516041204977" duration="1640000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="43420000" />
</component>
<component name="ToolWindowManager">
<frame x="-3191" y="43" width="2661" height="1538" extended-state="0" />
<layout>
<window_info id="TypeScript" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32954547" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.11751152" sideWeight="0.5" order="3" side_tool="false" content_ui="combo" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
<window_info id="Docker" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="true" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.36969697" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="npm" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="true" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.329296" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="11" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32954547" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
<option name="exactExcludedFiles">
<list>
<option value="$PROJECT_DIR$/src/index.js.map" />
<option value="$PROJECT_DIR$/src/index.js" />
<option value="$PROJECT_DIR$/src/Engine.js.map" />
<option value="$PROJECT_DIR$/src/Engine.js" />
<option value="$PROJECT_DIR$/src/models/EntityInfo.js.map" />
<option value="$PROJECT_DIR$/src/models/IndexInfo.js.map" />
<option value="$PROJECT_DIR$/src/models/RelationInfo.js" />
<option value="$PROJECT_DIR$/src/models/IndexColumnInfo.js.map" />
<option value="$PROJECT_DIR$/src/models/IndexInfo.js" />
<option value="$PROJECT_DIR$/src/models/ColumnInfo.js" />
<option value="$PROJECT_DIR$/src/models/RelationTempInfo.js.map" />
<option value="$PROJECT_DIR$/src/models/IndexColumnInfo.js" />
<option value="$PROJECT_DIR$/src/models/ColumnInfo.js.map" />
<option value="$PROJECT_DIR$/src/models/EntityInfo.js" />
<option value="$PROJECT_DIR$/src/models/DatabaseModel.js" />
<option value="$PROJECT_DIR$/src/models/RelationTempInfo.js" />
<option value="$PROJECT_DIR$/src/models/DatabaseModel.js.map" />
<option value="$PROJECT_DIR$/src/models/RelationInfo.js.map" />
<option value="$PROJECT_DIR$/src/drivers/PostgresDriver.js.map" />
<option value="$PROJECT_DIR$/src/drivers/MariaDbDriver.js.map" />
<option value="$PROJECT_DIR$/src/drivers/AbstractDriver.js.map" />
<option value="$PROJECT_DIR$/src/drivers/MariaDbDriver.js" />
<option value="$PROJECT_DIR$/src/drivers/MssqlDriver.js.map" />
<option value="$PROJECT_DIR$/src/drivers/MysqlDriver.js.map" />
<option value="$PROJECT_DIR$/src/drivers/MysqlDriver.js" />
<option value="$PROJECT_DIR$/src/drivers/MssqlDriver.js" />
<option value="$PROJECT_DIR$/src/drivers/AbstractDriver.js" />
<option value="$PROJECT_DIR$/src/drivers/PostgresDriver.js" />
<option value="$PROJECT_DIR$/test/utils/EntityFileToJson.js.map" />
<option value="$PROJECT_DIR$/test/utils/EntityFileToJson.js" />
<option value="$PROJECT_DIR$/test/drivers/MssqlDriver.test.js.map" />
<option value="$PROJECT_DIR$/test/drivers/MssqlDriver.test.js" />
<option value="$PROJECT_DIR$/test/integration/integration.test.js" />
<option value="$PROJECT_DIR$/test/integration/integration.test.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample16-indexes/entity/Post.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample16-indexes/entity/Post.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostInformation.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostCategory.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostMetadata.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostMetadata.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/Post.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostAuthor.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostDetails.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostDetails.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostImage.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostImage.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostInformation.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/Post.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostCategory.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample2-one-to-one/entity/PostAuthor.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample17-versioning/entity/Post.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample17-versioning/entity/Post.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostInformation.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostCategory.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostMetadata.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostMetadata.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/Post.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostAuthor.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostDetails.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostDetails.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostImage.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostImage.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostInformation.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/Post.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostCategory.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample3-many-to-one/entity/PostAuthor.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample1-simple-entity/entity/Post.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample1-simple-entity/entity/Post.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample11-all-types-entity/entity/EverythingEntity.js" />
<option value="$PROJECT_DIR$/test/integration/examples/sample11-all-types-entity/entity/EverythingEntity.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample27-composite-primary-keys/entity/Post.js.map" />
<option value="$PROJECT_DIR$/test/integration/examples/sample27-composite-primary-keys/entity/Post.js" />
<option value="$PROJECT_DIR$/../movebe-server/firebase-server/functions/index.js.map" />
<option value="$PROJECT_DIR$/../movebe-server/firebase-server/functions/index.js" />
<option value="$PROJECT_DIR$/../movebe-app/node_modules/karma/config.tpl.js" />
</list>
</option>
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State>
<option name="RECENTLY_FILTERED_USER_GROUPS">
<collection />
</option>
<option name="RECENTLY_FILTERED_BRANCH_GROUPS">
<collection />
</option>
<option name="COLUMN_ORDER">
<list>
<option value="0" />
<option value="1" />
<option value="2" />
<option value="3" />
</list>
</option>
</State>
</value>
</entry>
</map>
</option>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
<watches-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/dist/test/integration/examples/sample2-one-to-one/entity/Post.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1023">
<caret line="33" column="29" lean-forward="true" selection-start-line="33" selection-start-column="29" selection-end-line="33" selection-end-column="29" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/EntityInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="217">
<caret line="7" column="22" lean-forward="false" selection-start-line="7" selection-start-column="22" selection-end-line="7" selection-end-column="22" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/index.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1643">
<caret line="60" column="28" lean-forward="false" selection-start-line="60" selection-start-column="28" selection-end-line="60" selection-end-column="28" />
<folding>
<element signature="e#0#58#0" expanded="true" />
<marker date="1516041800196" expanded="true" signature="2862:2898" ph="{&quot;host&quot;: argv.h...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/test/integration/integration.test.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2480">
<caret line="80" column="84" lean-forward="false" selection-start-line="80" selection-start-column="84" selection-end-line="80" selection-end-column="84" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/entity.mst">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/DatabaseModel.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="248">
<caret line="8" column="4" lean-forward="false" selection-start-line="8" selection-start-column="4" selection-end-line="8" selection-end-column="4" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="186">
<caret line="6" column="20" lean-forward="false" selection-start-line="6" selection-start-column="18" selection-end-line="6" selection-end-column="20" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tsconfig.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="186">
<caret line="6" column="14" lean-forward="false" selection-start-line="6" selection-start-column="14" selection-end-line="6" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Engine.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1054">
<caret line="39" column="76" lean-forward="false" selection-start-line="39" selection-start-column="76" selection-end-line="39" selection-end-column="76" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.idea/codeStyleSettings.xml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/EntityInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="899">
<caret line="29" column="0" lean-forward="false" selection-start-line="10" selection-start-column="0" selection-end-line="29" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/index.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1426">
<caret line="53" column="0" lean-forward="false" selection-start-line="53" selection-start-column="0" selection-end-line="53" selection-end-column="0" />
<folding>
<element signature="e#0#58#0" expanded="true" />
<marker date="1516041800196" expanded="true" signature="2862:2898" ph="{&quot;host&quot;: argv.h...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/ColumnInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="434">
<caret line="14" column="43" lean-forward="false" selection-start-line="14" selection-start-column="43" selection-end-line="14" selection-end-column="43" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/RelationInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="403">
<caret line="13" column="5" lean-forward="false" selection-start-line="13" selection-start-column="5" selection-end-line="13" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/entity.mst">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="31">
<caret line="1" column="19" lean-forward="false" selection-start-line="1" selection-start-column="19" selection-end-line="1" selection-end-column="19" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/drivers/MysqlDriver.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="8773">
<caret line="283" column="61" lean-forward="false" selection-start-line="283" selection-start-column="61" selection-end-line="283" selection-end-column="61" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/test/utils/EntityFileToJson.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3317">
<caret line="107" column="146" lean-forward="false" selection-start-line="107" selection-start-column="146" selection-end-line="107" selection-end-column="146" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1023">
<caret line="33" column="13" lean-forward="false" selection-start-line="33" selection-start-column="13" selection-end-line="33" selection-end-column="13" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Engine.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="775">
<caret line="30" column="36" lean-forward="false" selection-start-line="30" selection-start-column="36" selection-end-line="30" selection-end-column="36" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Engine.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1488">
<caret line="48" column="17" lean-forward="false" selection-start-line="48" selection-start-column="17" selection-end-line="48" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/index.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="7" lean-forward="false" selection-start-line="0" selection-start-column="7" selection-end-line="0" selection-end-column="7" />
<folding>
<element signature="e#0#58#0" expanded="true" />
<marker date="1516041800196" expanded="true" signature="2862:2898" ph="{&quot;host&quot;: argv.h...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/src/Engine.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1488">
<caret line="48" column="35" lean-forward="false" selection-start-line="48" selection-start-column="35" selection-end-line="48" selection-end-column="35" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tslint.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="155">
<caret line="5" column="0" lean-forward="false" selection-start-line="1" selection-start-column="0" selection-end-line="5" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/src/drivers/MysqlDriver.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="806">
<caret line="26" column="41" lean-forward="false" selection-start-line="26" selection-start-column="41" selection-end-line="26" selection-end-column="41" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/RelationTempInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="93">
<caret line="3" column="4" lean-forward="false" selection-start-line="3" selection-start-column="4" selection-end-line="3" selection-end-column="4" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/drivers/MssqlDriver.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="369">
<caret line="301" column="64" lean-forward="false" selection-start-line="301" selection-start-column="53" selection-end-line="301" selection-end-column="68" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/test/utils/EntityFileToJson.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3317">
<caret line="107" column="146" lean-forward="false" selection-start-line="107" selection-start-column="146" selection-end-line="107" selection-end-column="146" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/src/ormconfig.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/src/tsconfig.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/src/Engine.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="245">
<caret line="48" column="35" lean-forward="false" selection-start-line="48" selection-start-column="35" selection-end-line="48" selection-end-column="35" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Engine.js.map">
<provider editor-type-id="sourcemapFileViewerProvider">
<state />
</provider>
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/tsconfig.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="186">
<caret line="6" column="14" lean-forward="false" selection-start-line="6" selection-start-column="14" selection-end-line="6" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/RelationInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="403">
<caret line="13" column="5" lean-forward="false" selection-start-line="13" selection-start-column="5" selection-end-line="13" selection-end-column="5" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Engine.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="775">
<caret line="55" column="0" lean-forward="false" selection-start-line="49" selection-start-column="0" selection-end-line="55" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.idea/codeStyleSettings.xml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/DatabaseModel.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="248">
<caret line="8" column="4" lean-forward="false" selection-start-line="8" selection-start-column="4" selection-end-line="8" selection-end-column="4" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/test/integration/integration.test.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="179">
<caret line="141" column="49" lean-forward="false" selection-start-line="141" selection-start-column="49" selection-end-line="141" selection-end-column="49" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/docker-compose.yml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="403">
<caret line="13" column="10" lean-forward="false" selection-start-line="13" selection-start-column="10" selection-end-line="13" selection-end-column="10" />
<folding>
<marker date="1516041617309" expanded="true" signature="13:786" ph="services: &lt;4 keys&gt;" />
<marker date="1516041617309" expanded="true" signature="54:66" ph="mysql:5.7.10" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/test/integration/integration.test.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="549">
<caret line="80" column="84" lean-forward="false" selection-start-line="80" selection-start-column="84" selection-end-line="80" selection-end-column="84" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/test/integration/examples/sample2-one-to-one/entity/Post.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="754">
<caret line="33" column="29" lean-forward="false" selection-start-line="33" selection-start-column="29" selection-end-line="33" selection-end-column="29" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/test/integration/examples/sample1-simple-entity/entity/Post.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/test/integration/examples/sample1-simple-entity/entity/Post.js.map">
<provider editor-type-id="sourcemapFileViewerProvider">
<state />
</provider>
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/README.md">
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]">
<state split_layout="SPLIT">
<first_editor relative-caret-position="31">
<caret line="25" column="0" lean-forward="false" selection-start-line="25" selection-start-column="0" selection-end-line="25" selection-end-column="0" />
</first_editor>
<second_editor />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/dist/src/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="992">
<caret line="32" column="44" lean-forward="false" selection-start-line="32" selection-start-column="44" selection-end-line="32" selection-end-column="44" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/index.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1178">
<caret line="45" column="53" lean-forward="false" selection-start-line="45" selection-start-column="53" selection-end-line="45" selection-end-column="53" />
<folding>
<element signature="e#0#58#0" expanded="true" />
<marker date="1516041800196" expanded="true" signature="2862:2898" ph="{&quot;host&quot;: argv.h...}" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/EntityInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="217">
<caret line="7" column="22" lean-forward="false" selection-start-line="7" selection-start-column="22" selection-end-line="7" selection-end-column="22" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/models/ColumnInfo.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="155">
<caret line="5" column="25" lean-forward="false" selection-start-line="5" selection-start-column="25" selection-end-line="5" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/entity.mst">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="713">
<caret line="23" column="17" lean-forward="false" selection-start-line="23" selection-start-column="17" selection-end-line="23" selection-end-column="17" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Engine.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="233">
<caret line="37" column="23" lean-forward="false" selection-start-line="37" selection-start-column="23" selection-end-line="37" selection-end-column="23" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/drivers/MysqlDriver.ts">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="545">
<caret line="68" column="30" lean-forward="false" selection-start-line="68" selection-start-column="30" selection-end-line="68" selection-end-column="30" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="527">
<caret line="35" column="18" lean-forward="false" selection-start-line="35" selection-start-column="18" selection-end-line="35" selection-end-column="18" />
<folding />
</state>
</provider>
</entry>
</component>
</project>

View File

@ -1,28 +1,30 @@
language: node_js
node_js:
- stable
- 7
- 6
- 5
- stable
- 8
- 6
sudo: required
services:
- docker
- docker
env:
- MSSQL_Skip=0 MSSQL_Host=localhost MSSQL_Port=1433 MSSQL_Username=sa MSSQL_Password=!Passw0rd MSSQL_Database=typeorm_mg POSTGRES_Skip=0 POSTGRES_Host=localhost POSTGRES_Port=5432 POSTGRES_Username=postgres POSTGRES_Password=!Passw0rd POSTGRES_Database=typeorm_mg MYSQL_Skip=0 MYSQL_Host=localhost MYSQL_Port=3306 MYSQL_Username=root MYSQL_Password=!Passw0rd MYSQL_Database=typeorm_mg MARIADB_Skip=0 MARIADB_Host=localhost MARIADB_Port=3307 MARIADB_Username=root MARIADB_Password=!Passw0rd MARIADB_Database=typeorm_mg
matrix:
- POSTGRES_Skip=0 POSTGRES_Host=localhost POSTGRES_Port=5432 POSTGRES_Username=postgres
POSTGRES_Password=!Passw0rd POSTGRES_Database=typeorm_mg POSTGRES_SSL=0 MYSQL_Skip=0
MYSQL_Host=localhost MYSQL_Port=3306 MYSQL_Username=root MYSQL_Password=!Passw0rd
MYSQL_Database=typeorm_mg MYSQL_SSL=1 MARIADB_Skip=0 MARIADB_Host=localhost MARIADB_Port=3307
MARIADB_Username=root MARIADB_Password=!Passw0rd MARIADB_Database=typeorm_mg MARIADB_SSL=0
global:
secure: Xj6wO8aghAhi6nvBI/HTtW9mIq9xfigIQfCC7ZkgAcqS4Oe3ba+7A5pCJq6Fxndadc6Bg1bZ3BGCH3Upf/Yv3zCFybsk43LwwXPJoG9gCrva/me7Sd+ws30EcD2dsKbvjZqNYai/XdrhzJY+KlxWvS/g3N/puBNffcU5hteo1zllxakQIAiavJ64D4g+Th8LSytmb2qDDToSsCxXkzNSutaKgZSf6T8QCWzcl0NCZkl69s9kX7L5335HVBD9lR/EKFC4wqHQjryCDRAyNRvItZRNlTPqgOI8lvcTsH9zKozDwEz7h/zcLebbY/+YTsLB5pb2sa62tkQE0x24TG7bLxujQShEQZU8itkRSV+w6+0JpBHQPlSUppkQJBNGKao7GaO/Eix4mSyvHkeECmTWDtEpBGWERYLqCKGe2Nj3BfcA2Ue6pjz9CX8wnrCbx53j6be3M/g/gcx7fbJbX3P95yc1CWAaR+tJKlP38rTcyo+o+Db1Ft0pzRJyZGmkGGPnCj6LxWYSmVqumLYDyqAMBDcQYuVwaKaTsJtU/2OBb3+zjKmWivV+19SXBqILvFbLv9IYLavpMr9OAwDGcJu0+mF+VCjGkZTlBxWJ53PmCoIJ6Qx/5o67LsCYL4L/hugNETlOEEKwe/k1mBraYWB0jI3mBUCV0d8J5P+ZQhwIZo4=
before_install:
- sudo service mysql stop
- sudo service postgresql stop
- docker-compose up -d
- sudo service mysql stop
- sudo service postgresql stop
- docker-compose up -d
- npm install -g npm@5
- npm install -g greenkeeper-lockfile@1
before_script:
- npm run typings-install
- npm link typescript
- tsc
- sleep 20s
- greenkeeper-lockfile-update
- npm run typings-install
- npm link typescript
- tsc
after_script:
- greenkeeper-lockfile-upload

View File

@ -1,4 +1,6 @@
# typeorm-model-generator
[![Greenkeeper badge](https://badges.greenkeeper.io/Kononnable/typeorm-model-generator.svg)](https://greenkeeper.io/)
[![Build Status](https://travis-ci.org/Kononnable/typeorm-model-generator.svg?branch=master)](https://travis-ci.org/Kononnable/typeorm-model-generator)
[![npm version](https://badge.fury.io/js/typeorm-model-generator.svg)](https://badge.fury.io/js/typeorm-model-generator)
[![codecov](https://codecov.io/gh/Kononnable/typeorm-model-generator/branch/master/graph/badge.svg)](https://codecov.io/gh/Kononnable/typeorm-model-generator)
@ -33,7 +35,8 @@ Options:
-e, --engine Database engine.
[choices: "mssql", "postgres", "mysql", "mariadb"] [default: "mssql"]
-o, --output Where to place generated models.
-c, --case Convert snake_case tables names to PascalCase entities and snake_case columns to camelCase properties
-s, --schema Schema name to create model from. Only for mssql and postgres.
--ssl [boolean] [default: false]
```
### Examples
@ -46,12 +49,12 @@ Options:
```
npx typeorm-model-generator -h localhost -d tempdb -u sa -x !Passw0rd -e mssql -o .\
````
* Creating model from local Postgres database
* Creating model from local Postgres database, public schema with ssl connection
* Global module
```
typeorm-model-generator -h localhost -d postgres -u postgres -x !Passw0rd -e postgres -o .\
typeorm-model-generator -h localhost -d postgres -u postgres -x !Passw0rd -e postgres -o .\ -s public --ssl
````
* Npx Way
```
npx typeorm-model-generator -h localhost -d postgres -u postgres -x !Passw0rd -e postgres -o .\
npx typeorm-model-generator -h localhost -d postgres -u postgres -x !Passw0rd -e postgres -o .\ -s public --ssl
````

View File

@ -3,8 +3,8 @@ services:
# mysql
mysql:
image: "mysql:5.7.10"
container_name: "typeorm-mysql"
image: "mysql:5.7.19"
container_name: "typeorm-mg-mysql"
ports:
- "3306:3306"
environment:
@ -12,8 +12,8 @@ services:
# mariadb
mariadb:
image: "mariadb:10.1.16"
container_name: "typeorm-mariadb"
image: "mariadb:10.2.9"
container_name: "typeorm-mg-mariadb"
ports:
- "3307:3306"
environment:
@ -21,19 +21,20 @@ services:
# postgres
postgres:
image: "postgres:9.6.1"
container_name: "typeorm-postgres"
image: "postgres:10.0"
container_name: "typeorm-mg-postgres"
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: "!Passw0rd"
# mssql
mssql:
image: "microsoft/mssql-server-linux:ctp2-1"
container_name: "typeorm-mssql"
ports:
- "1433:1433"
environment:
ACCEPT_EULA: "Y"
SA_PASSWORD: "!Passw0rd"
# # mssql
# mssql:
# image: "microsoft/mssql-server-linux:2017-GA"
# container_name: "typeorm-mg-mssql"
# ports:
# - "1433:1433"
# environment:
# ACCEPT_EULA: "Y"
# SA_PASSWORD: "!Passw0rd"

1583
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "typeorm-model-generator",
"version": "0.2.0",
"version": "0.2.4",
"description": "Generates models for TypeORM from existing databases.",
"bin": "bin/typeorm-model-generator",
"scripts": {
@ -24,39 +24,40 @@
},
"homepage": "https://github.com/Kononnable/typeorm-model-generator#readme",
"dependencies": {
"@types/mysql": "0.0.34",
"@types/pg": "^6.1.41",
"change-case": "^3.0.1",
"handlebars": "^4.0.10",
"mssql": "^3.3.0",
"mysql": "^2.14.1",
"pg": "^6.4.0",
"handlebars": "^4.0.11",
"mssql": "^4.0.4",
"mysql": "^2.15.0",
"pg": "^7.4.0",
"reflect-metadata": "^0.1.10",
"typeorm": "0.0.10",
"typescript": "^2.4.0",
"yargs": "^7.0.2"
"typeorm": "^0.1.3",
"typescript": "^2.6.1",
"yargs": "^10.0.3",
"yn": "^2.0.0"
},
"devDependencies": {
"@types/chai": "^3.5.2",
"@types/chai-as-promised": "0.0.30",
"@types/chai-subset": "^1.3.0",
"@types/fs-extra": "^3.0.0",
"@types/handlebars": "^4.0.32",
"@types/mocha": "^2.2.41",
"@types/mssql": "^3.3.0",
"@types/node": "^7.0.39",
"@types/sinon": "^2.1.3",
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"chai-subset": "^1.5.0",
"codecov": "^2.1.0",
"@types/chai": "^4.0.5",
"@types/chai-as-promised": "7.1.0",
"@types/chai-subset": "^1.3.1",
"@types/fs-extra": "^5.0.0",
"@types/handlebars": "^4.0.36",
"@types/mocha": "^2.2.44",
"@types/mssql": "^4.0.4",
"@types/mysql": "2.15.2",
"@types/node": "^9.3.0",
"@types/pg": "^7.4.1",
"@types/sinon": "^4.1.2",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"chai-subset": "^1.6.0",
"codecov": "^3.0.0",
"dotenv": "^4.0.0",
"fs-extra": "^3.0.1",
"fs-extra": "^5.0.0",
"istanbul": "^0.4.5",
"mocha": "^3.3.0",
"mocha": "^4.0.1",
"remap-istanbul": "^0.9.5",
"sinon": "^2.2.0",
"sinon-chai": "^2.10.0",
"typings": "^2.1.0"
"sinon": "^4.1.2",
"sinon-chai": "^2.14.0",
"typings": "^2.1.1"
}
}

View File

@ -12,7 +12,7 @@ export class Engine {
}
public async createModelFromDatabase(): Promise<boolean> {
let dbModel = await this.getEntitiesInfo(this.Options.databaseName, this.Options.host, this.Options.port, this.Options.user, this.Options.password);
let dbModel = await this.getEntitiesInfo(this.Options.databaseName, this.Options.host, this.Options.port, this.Options.user, this.Options.password, this.Options.schemaName, this.Options.ssl);
if (dbModel.entities.length > 0) {
this.createModelFromMetadata(dbModel);
} else {
@ -20,8 +20,8 @@ export class Engine {
}
return true;
}
private async getEntitiesInfo(database: string, server: string, port: number, user: string, password: string): Promise<DatabaseModel> {
return await this.driver.GetDataFromServer(database, server, port, user, password)
private async getEntitiesInfo(database: string, server: string, port: number, user: string, password: string, schemaName:string, ssl:boolean): Promise<DatabaseModel> {
return await this.driver.GetDataFromServer(database, server, port, user, password,schemaName,ssl)
}
private createModelFromMetadata(databaseModel: DatabaseModel) {
@ -99,5 +99,7 @@ export interface EngineOptions {
password: string,
resultsPath: string,
databaseType: string,
schemaName:string,
ssl:boolean,
convertCase: boolean
}

View File

@ -4,22 +4,22 @@ import { DatabaseModel } from './../models/DatabaseModel'
* AbstractDriver
*/
export abstract class AbstractDriver {
async GetDataFromServer(database: string, server: string, port: number, user: string, password: string): Promise<DatabaseModel> {
async GetDataFromServer(database: string, server: string, port: number, user: string, password: string, schema:string, ssl:boolean): Promise<DatabaseModel> {
let dbModel = <DatabaseModel>{};
await this.ConnectToServer(database, server, port, user, password);
dbModel.entities = await this.GetAllTables();
await this.GetCoulmnsFromEntity(dbModel.entities);
await this.GetIndexesFromEntity(dbModel.entities);
dbModel.entities = await this.GetRelations(dbModel.entities);
await this.ConnectToServer(database, server, port, user, password,ssl);
dbModel.entities = await this.GetAllTables(schema);
await this.GetCoulmnsFromEntity(dbModel.entities,schema);
await this.GetIndexesFromEntity(dbModel.entities,schema);
dbModel.entities = await this.GetRelations(dbModel.entities,schema);
await this.DisconnectFromServer();
this.FindPrimaryColumnsFromIndexes(dbModel)
return dbModel;
}
abstract async ConnectToServer(database: string, server: string, port: number, user: string, password: string);
abstract async GetAllTables(): Promise<EntityInfo[]>
abstract async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]>;
abstract async GetIndexesFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]>;
abstract async GetRelations(entities: EntityInfo[]): Promise<EntityInfo[]>;
abstract async ConnectToServer(database: string, server: string, port: number, user: string, password: string,ssl:boolean);
abstract async GetAllTables(schema:string): Promise<EntityInfo[]>
abstract async GetCoulmnsFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async GetIndexesFromEntity(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async GetRelations(entities: EntityInfo[],schema:string): Promise<EntityInfo[]>;
abstract async FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel);
abstract async DisconnectFromServer();

View File

@ -4,404 +4,11 @@ import { ColumnInfo } from './../models/ColumnInfo'
import { EntityInfo } from './../models/EntityInfo'
import { RelationInfo } from './../models/RelationInfo'
import { DatabaseModel } from './../models/DatabaseModel'
import { MysqlDriver } from './MysqlDriver';
/**
* MariaDb
*/
export class MariaDbDriver extends AbstractDriver {
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
if (!primaryIndex) {
console.error(`Table ${entity.EntityName} has no PK.`)
return;
}
entity.Columns.forEach(col => {
if (primaryIndex!.columns.some(cIndex => cIndex.name == col.name)) col.isPrimary = true
})
});
}
async GetAllTables(): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{ TABLE_SCHEMA: string, TABLE_NAME: string }>(`SELECT TABLE_SCHEMA, TABLE_NAME
FROM information_schema.tables
WHERE table_type='BASE TABLE'
AND table_schema like DATABASE()`);
let ret: EntityInfo[] = <EntityInfo[]>[];
response.forEach((val) => {
let ent: EntityInfo = new EntityInfo();
ent.EntityName = val.TABLE_NAME;
ent.Columns = <ColumnInfo[]>[];
ent.Indexes = <IndexInfo[]>[];
ret.push(ent);
})
return ret;
}
async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
NUMERIC_PRECISION: number, NUMERIC_SCALE: number, IsIdentity: number
}>(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,
CASE WHEN EXTRA like '%auto_increment%' THEN 1 ELSE 0 END IsIdentity FROM INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA like DATABASE()`);
entities.forEach((ent) => {
response.filter((filterVal) => {
return filterVal.TABLE_NAME == ent.EntityName;
}).forEach((resp) => {
let colInfo: ColumnInfo = new ColumnInfo();
colInfo.name = resp.COLUMN_NAME;
colInfo.is_nullable = resp.IS_NULLABLE == 'YES' ? true : false;
colInfo.is_generated = resp.IsIdentity == 1 ? true : false;
colInfo.default = resp.COLUMN_DEFAULT;
switch (resp.DATA_TYPE) {
case "int":
colInfo.ts_type = "number"
colInfo.sql_type = "int"
break;
case "tinyint":
if (resp.NUMERIC_PRECISION == 3) {
colInfo.ts_type = "boolean"
colInfo.sql_type = "boolean"
} else {
colInfo.ts_type = "number"
colInfo.sql_type = "smallint"
}
break;
case "smallint":
colInfo.ts_type = "number"
colInfo.sql_type = "smallint"
break;
case "bit":
colInfo.ts_type = "boolean"
colInfo.sql_type = "boolean"
break;
case "float":
colInfo.ts_type = "number"
colInfo.sql_type = "float"
break;
case "bigint":
colInfo.ts_type = "number"
colInfo.sql_type = "bigint"
break;
case "date":
colInfo.ts_type = "Date"
colInfo.sql_type = "date"
break;
case "time":
colInfo.ts_type = "Date"
colInfo.sql_type = "time"
break;
case "datetime":
colInfo.ts_type = "Date";
colInfo.sql_type = "datetime"
break;
case "char":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
break;
case "nchar":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
break;
case "text":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
break;
case "ntext":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
break;
case "varchar":
colInfo.ts_type = "string"
colInfo.sql_type = "string"
break;
case "nvarchar":
colInfo.ts_type = "string"
colInfo.sql_type = "string"
break;
case "money":
colInfo.ts_type = "number"
colInfo.sql_type = "decimal"
break;
case "real":
colInfo.ts_type = "number"
colInfo.sql_type = "double"
break;
case "double":
colInfo.ts_type = "number"
colInfo.sql_type = "double"
break;
case "decimal":
colInfo.ts_type = "number"
colInfo.sql_type = "decimal"
colInfo.numericPrecision = resp.NUMERIC_PRECISION
colInfo.numericScale = resp.NUMERIC_SCALE
break;
case "xml":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
break;
default:
console.error("Unknown column type:" + resp.DATA_TYPE);
break;
}
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
if (colInfo.sql_type) ent.Columns.push(colInfo);
})
})
return entities;
}
async GetIndexesFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TableName: string, IndexName: string, ColumnName: string, is_unique: number,
is_primary_key: number//, is_descending_key: number//, is_included_column: number
}>(`SELECT TABLE_NAME TableName,INDEX_NAME IndexName,COLUMN_NAME ColumnName,CASE WHEN NON_UNIQUE=0 THEN 1 ELSE 0 END is_unique,
CASE WHEN INDEX_NAME='PRIMARY' THEN 1 ELSE 0 END is_primary_key
FROM information_schema.statistics sta
WHERE table_schema like DATABASE();
`);
entities.forEach((ent) => {
response.filter((filterVal) => {
return filterVal.TableName == ent.EntityName;
}).forEach((resp) => {
let indexInfo: IndexInfo = <IndexInfo>{};
let indexColumnInfo: IndexColumnInfo = <IndexColumnInfo>{};
if (ent.Indexes.filter((filterVal) => {
return filterVal.name == resp.IndexName
}).length > 0) {
indexInfo = ent.Indexes.filter((filterVal) => {
return filterVal.name == resp.IndexName
})[0];
} else {
indexInfo.columns = <IndexColumnInfo[]>[];
indexInfo.name = resp.IndexName;
indexInfo.isUnique = resp.is_unique == 1 ? true : false;
indexInfo.isPrimaryKey = resp.is_primary_key == 1 ? true : false;
ent.Indexes.push(indexInfo);
}
indexColumnInfo.name = resp.ColumnName;
// indexColumnInfo.isIncludedColumn = resp.is_included_column == 1 ? true : false;
// indexColumnInfo.isDescending = resp.is_descending_key == 1 ? true : false;
indexInfo.columns.push(indexColumnInfo);
})
})
return entities;
}
async GetRelations(entities: EntityInfo[]): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string,
TableReferenced: string, ForeignKeyColumnReferenced: string,
onDelete: "RESTRICT" | "CASCADE" | "SET NULL",
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL", object_id: string
}>(`SELECT
CU.TABLE_NAME TableWithForeignKey,
CU.ORDINAL_POSITION FK_PartNo,
CU.COLUMN_NAME ForeignKeyColumn,
CU.REFERENCED_TABLE_NAME TableReferenced,
CU.REFERENCED_COLUMN_NAME ForeignKeyColumnReferenced,
RC.DELETE_RULE onDelete,
RC.UPDATE_RULE onUpdate,
CU.CONSTRAINT_NAME object_id
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU
JOIN
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC ON CU.CONSTRAINT_NAME=RC.CONSTRAINT_NAME
WHERE
TABLE_SCHEMA = SCHEMA()
AND CU.REFERENCED_TABLE_NAME IS NOT NULL;
`);
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
response.forEach((resp) => {
let rels = relationsTemp.find((val) => {
return val.object_id == resp.object_id;
})
if (rels == undefined) {
rels = <RelationTempInfo>{};
rels.ownerColumnsNames = [];
rels.referencedColumnsNames = [];
rels.actionOnDelete = resp.onDelete;
rels.actionOnUpdate = resp.onUpdate;
rels.object_id = resp.object_id;
rels.ownerTable = resp.TableWithForeignKey;
rels.referencedTable = resp.TableReferenced;
relationsTemp.push(rels);
}
rels.ownerColumnsNames.push(resp.ForeignKeyColumn);
rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced);
})
relationsTemp.forEach((relationTmp) => {
let ownerEntity = entities.find((entitity) => {
return entitity.EntityName == relationTmp.ownerTable;
})
if (!ownerEntity) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.ownerTable}.`)
return;
}
let referencedEntity = entities.find((entitity) => {
return entitity.EntityName == relationTmp.referencedTable;
})
if (!referencedEntity) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity model ${relationTmp.referencedTable}.`)
return;
}
let ownerColumn = ownerEntity.Columns.find((column) => {
return column.name == relationTmp.ownerColumnsNames[0];
})
if (!ownerColumn) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.ownerTable}.${ownerColumn}.`)
return;
}
let relatedColumn = referencedEntity.Columns.find((column) => {
return column.name == relationTmp.referencedColumnsNames[0];
})
if (!relatedColumn) {
console.error(`Relation between tables ${relationTmp.ownerTable} and ${relationTmp.referencedTable} didn't found entity column ${relationTmp.referencedTable}.${relatedColumn}.`)
return;
}
let ownColumn: ColumnInfo = ownerColumn;
let isOneToMany: boolean;
isOneToMany = false;
let index = ownerEntity.Indexes.find(
(index) => {
return index.isUnique && index.columns.some(col => {
return col.name == ownerColumn!.name
})
}
)
if (!index) {
isOneToMany = true;
} else {
isOneToMany = false;
}
let ownerRelation = new RelationInfo()
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
ownerRelation.isOwner = true
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
ownerRelation.relatedTable = relationTmp.referencedTable
ownerRelation.ownerTable = relationTmp.ownerTable
ownerRelation.ownerColumn = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
ownerColumn.relations.push(ownerRelation)
if (isOneToMany) {
let col = new ColumnInfo()
col.name = ownerEntity.EntityName.toLowerCase() + 's'
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
referencedRelation.isOwner = false
referencedRelation.relatedColumn = ownerColumn.name
referencedRelation.relatedTable = relationTmp.ownerTable
referencedRelation.ownerTable = relationTmp.referencedTable
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
referencedRelation.relationType = "OneToMany"
referencedEntity.Columns.push(col)
} else {
let col = new ColumnInfo()
col.name = ownerEntity.EntityName.toLowerCase()
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate
referencedRelation.isOwner = false
referencedRelation.relatedColumn = ownerColumn.name
referencedRelation.relatedTable = relationTmp.ownerTable
referencedRelation.ownerTable = relationTmp.referencedTable
referencedRelation.ownerColumn = relatedColumn.name.toLowerCase()
referencedRelation.relationType = "OneToOne"
referencedEntity.Columns.push(col)
}
})
return entities;
}
async DisconnectFromServer() {
let promise = new Promise<boolean>(
(resolve, reject) => {
this.Connection.end((err) => {
if (!err) {
//Connection successfull
resolve(true)
}
else {
console.error('Error disconnecting to MariaDb Server.')
console.error(err.message)
process.abort()
reject(err)
}
});
}
)
if (this.Connection)
await promise;
}
private Connection: MariaDb.IConnection;
async ConnectToServer(database: string, server: string, port: number, user: string, password: string) {
let config: MariaDb.IConnectionConfig = {
database: database,
host: server,
port: port,
user: user,
password: password,
}
let promise = new Promise<boolean>(
(resolve, reject) => {
this.Connection = MariaDb.createConnection(config)
this.Connection.connect((err) => {
if (!err) {
//Connection successfull
resolve(true)
}
else {
console.error('Error connecting to MariaDb Server.')
console.error(err.message)
process.abort()
reject(err)
}
});
}
)
await promise;
}
async CreateDB(dbName: string) {
let resp = await this.ExecQuery<any>(`CREATE DATABASE ${dbName}; `)
}
async UseDB(dbName: string) {
let resp = await this.ExecQuery<any>(`USE ${dbName}; `)
}
async DropDB(dbName: string) {
let resp = await this.ExecQuery<any>(`DROP DATABASE ${dbName}; `)
}
async CheckIfDBExists(dbName: string): Promise<boolean> {
let resp = await this.ExecQuery<any>(`SHOW DATABASES LIKE '${dbName}' `)
return resp.length > 0;
}
async ExecQuery<T>(sql: string): Promise<Array<T>> {
let ret: Array<T> = [];
let that = this;
let query = this.Connection.query(sql)
let stream = query.stream({});
let promise = new Promise<boolean>(
(resolve, reject) => {
stream.on('data',
chunk => {
ret.push(<T><any>chunk)
});
stream.on('end', () => resolve(true));
})
await promise;
return ret;
}
export class MariaDbDriver extends MysqlDriver {
readonly EngineName:string = 'MariaDb'
}

View File

@ -21,10 +21,10 @@ export class MssqlDriver extends AbstractDriver {
});
}
async GetAllTables(): Promise<EntityInfo[]> {
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let request = new MSSQL.Request(this.Connection)
let response: { TABLE_SCHEMA: string, TABLE_NAME: string }[]
= await request.query("SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'");
= (await request.query(`SELECT TABLE_SCHEMA,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA='${schema}'`)).recordset;
let ret: EntityInfo[] = <EntityInfo[]>[];
response.forEach((val) => {
let ent: EntityInfo = new EntityInfo();
@ -35,16 +35,16 @@ export class MssqlDriver extends AbstractDriver {
})
return ret;
}
async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let request = new MSSQL.Request(this.Connection)
let response: {
TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
NUMERIC_PRECISION: number, NUMERIC_SCALE: number, IsIdentity: number
}[]
= await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
= (await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,
DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,
COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS`);
COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA='${schema}'`)).recordset;
entities.forEach((ent) => {
response.filter((filterVal) => {
return filterVal.TABLE_NAME == ent.EntityName;
@ -58,14 +58,17 @@ export class MssqlDriver extends AbstractDriver {
case "int":
colInfo.ts_type = "number"
colInfo.sql_type = "int"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "tinyint":
colInfo.ts_type = "number"
colInfo.sql_type = "smallint"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "smallint":
colInfo.ts_type = "number"
colInfo.sql_type = "smallint"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "bit":
colInfo.ts_type = "boolean"
@ -74,10 +77,13 @@ export class MssqlDriver extends AbstractDriver {
case "float":
colInfo.ts_type = "number"
colInfo.sql_type = "float"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
colInfo.numericPrecision = resp.NUMERIC_PRECISION
break;
case "bigint":
colInfo.ts_type = "number"
colInfo.ts_type = "string"
colInfo.sql_type = "bigint"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "date":
colInfo.ts_type = "Date"
@ -93,11 +99,13 @@ export class MssqlDriver extends AbstractDriver {
break;
case "char":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
colInfo.sql_type = "char"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "nchar":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
colInfo.sql_type = "nchar"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "text":
colInfo.ts_type = "string"
@ -105,29 +113,81 @@ export class MssqlDriver extends AbstractDriver {
break;
case "ntext":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
colInfo.sql_type = "ntext"
break;
case "uniqueidentifier":
colInfo.ts_type = "string"
colInfo.sql_type = "uniqueidentifier"
break;
case "varchar":
colInfo.ts_type = "string"
colInfo.sql_type = "string"
colInfo.sql_type = "varchar"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "binary":
colInfo.ts_type = "Buffer"
colInfo.sql_type = "binary"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "varbinary":
colInfo.ts_type = "Buffer"
colInfo.sql_type = "varbinary"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "image":
colInfo.ts_type = "Buffer"
colInfo.sql_type = "image"
break;
case "nvarchar":
colInfo.ts_type = "string"
colInfo.sql_type = "string"
colInfo.sql_type = "nvarchar"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "money":
colInfo.ts_type = "number"
colInfo.sql_type = "decimal"
break;
case "smallmoney":
colInfo.ts_type = "number"
colInfo.sql_type = "smallmoney"
break;
case "real":
colInfo.ts_type = "number"
colInfo.sql_type = "double"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "decimal":
colInfo.ts_type = "number"
colInfo.sql_type = "decimal"
colInfo.numericPrecision = resp.NUMERIC_PRECISION
colInfo.numericScale = resp.NUMERIC_SCALE
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "numeric":
colInfo.ts_type = "number"
colInfo.sql_type = "numeric"
colInfo.numericPrecision = resp.NUMERIC_PRECISION
colInfo.numericScale = resp.NUMERIC_SCALE
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "datetime2":
colInfo.ts_type = "Date"
colInfo.sql_type = "datetime2"
colInfo.numericPrecision = resp.NUMERIC_PRECISION
break;
case "time":
colInfo.ts_type = "Date"
colInfo.sql_type = "time"
colInfo.numericPrecision = resp.NUMERIC_PRECISION
break;
case "datetimeoffset":
colInfo.ts_type = "Date"
colInfo.sql_type = "datetimeoffset"
colInfo.numericPrecision = resp.NUMERIC_PRECISION
break;
case "smalldatetime":
colInfo.ts_type = "Date"
colInfo.sql_type = "smalldatetime"
break;
case "xml":
colInfo.ts_type = "string"
@ -137,19 +197,19 @@ export class MssqlDriver extends AbstractDriver {
console.error("Unknown column type:" + resp.DATA_TYPE);
break;
}
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
if (colInfo.sql_type) ent.Columns.push(colInfo);
})
})
return entities;
}
async GetIndexesFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let request = new MSSQL.Request(this.Connection)
let response: {
TableName: string, IndexName: string, ColumnName: string, is_unique: number,
is_primary_key: number//, is_descending_key: number//, is_included_column: number
}[]
= await request.query(`SELECT
= (await request.query(`SELECT
TableName = t.name,
IndexName = ind.name,
ColumnName = col.name,
@ -165,10 +225,12 @@ INNER JOIN
sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
INNER JOIN
sys.tables t ON ind.object_id = t.object_id
INNER JOIN
sys.schemas s on s.schema_id=t.schema_id
WHERE
t.is_ms_shipped = 0
t.is_ms_shipped = 0 and s.name='${schema}'
ORDER BY
t.name, ind.name, ind.index_id, ic.key_ordinal;`);
t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset;
entities.forEach((ent) => {
response.filter((filterVal) => {
return filterVal.TableName == ent.EntityName;
@ -198,7 +260,7 @@ ORDER BY
return entities;
}
async GetRelations(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let request = new MSSQL.Request(this.Connection)
let response: {
TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string,
@ -206,7 +268,7 @@ ORDER BY
onDelete: "RESTRICT" | "CASCADE" | "SET NULL",
onUpdate: "RESTRICT" | "CASCADE" | "SET NULL", object_id: number
}[]
= await request.query(`select
= (await request.query(`select
parentTable.name as TableWithForeignKey,
fkc.constraint_column_id as FK_PartNo,
parentColumn.name as ForeignKeyColumn,
@ -227,10 +289,12 @@ inner join
sys.tables as referencedTable on fkc.referenced_object_id = referencedTable.object_id
inner join
sys.columns as referencedColumn on fkc.referenced_object_id = referencedColumn.object_id and fkc.referenced_column_id = referencedColumn.column_id
inner join
sys.schemas as parentSchema on parentSchema.schema_id=parentTable.schema_id
where
fk.is_disabled=0 and fk.is_ms_shipped=0
fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name='${schema}'
order by
TableWithForeignKey, FK_PartNo`);
TableWithForeignKey, FK_PartNo`)).recordset;
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
response.forEach((resp) => {
let rels = relationsTemp.find((val) => {
@ -295,18 +359,29 @@ order by
isOneToMany = false;
}
let ownerRelation = new RelationInfo()
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length>0){
for (let i=2;i<=ownerEntity.Columns.length;i++){
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')+i.toString();
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length==0) break;
}
}
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
ownerRelation.isOwner = true
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
ownerRelation.relatedTable = relationTmp.referencedTable
ownerRelation.ownerTable = relationTmp.ownerTable
ownerRelation.ownerColumn = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
ownerRelation.ownerColumn = columnName
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
ownerColumn.relations.push(ownerRelation)
if (isOneToMany) {
let col = new ColumnInfo()
col.name = ownerEntity.EntityName.toLowerCase() + 's'
col.name = columnName
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
@ -320,7 +395,7 @@ order by
referencedEntity.Columns.push(col)
} else {
let col = new ColumnInfo()
col.name = ownerEntity.EntityName.toLowerCase()
col.name = columnName
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
@ -342,8 +417,8 @@ order by
await this.Connection.close();
}
private Connection: MSSQL.Connection;
async ConnectToServer(database: string, server: string, port: number, user: string, password: string) {
private Connection: MSSQL.ConnectionPool;
async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean) {
let config: MSSQL.config = {
database: database,
server: server,
@ -351,7 +426,7 @@ order by
user: user,
password: password,
options: {
encrypt: true, // Use this if you're on Windows Azure
encrypt: ssl, // Use this if you're on Windows Azure
appName: 'typeorm-model-generator'
}
}
@ -359,7 +434,7 @@ order by
let promise = new Promise<boolean>(
(resolve, reject) => {
this.Connection = new MSSQL.Connection(config, (err) => {
this.Connection = new MSSQL.ConnectionPool(config, (err) => {
if (!err) {
//Connection successfull
resolve(true)
@ -391,6 +466,6 @@ order by
async CheckIfDBExists(dbName: string): Promise<boolean> {
let request = new MSSQL.Request(this.Connection);
let resp = await request.query(`SELECT name FROM master.sys.databases WHERE name = N'${dbName}' `)
return resp.length > 0;
return resp.recordset.length > 0;
}
}

View File

@ -8,6 +8,8 @@ import { DatabaseModel } from './../models/DatabaseModel'
* MysqlDriver
*/
export class MysqlDriver extends AbstractDriver {
readonly EngineName: string = 'MySQL'
FindPrimaryColumnsFromIndexes(dbModel: DatabaseModel) {
dbModel.entities.forEach(entity => {
let primaryIndex = entity.Indexes.find(v => v.isPrimaryKey);
@ -21,7 +23,7 @@ export class MysqlDriver extends AbstractDriver {
});
}
async GetAllTables(): Promise<EntityInfo[]> {
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{ TABLE_SCHEMA: string, TABLE_NAME: string }>(`SELECT TABLE_SCHEMA, TABLE_NAME
FROM information_schema.tables
@ -37,7 +39,7 @@ export class MysqlDriver extends AbstractDriver {
})
return ret;
}
async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
@ -59,19 +61,16 @@ export class MysqlDriver extends AbstractDriver {
case "int":
colInfo.ts_type = "number"
colInfo.sql_type = "int"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "tinyint":
if (resp.NUMERIC_PRECISION == 3) {
colInfo.ts_type = "boolean"
colInfo.sql_type = "boolean"
} else {
colInfo.ts_type = "number"
colInfo.sql_type = "smallint"
}
colInfo.ts_type = "number"
colInfo.sql_type = "tinyint"
break;
case "smallint":
colInfo.ts_type = "number"
colInfo.sql_type = "smallint"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "bit":
colInfo.ts_type = "boolean"
@ -80,17 +79,19 @@ export class MysqlDriver extends AbstractDriver {
case "float":
colInfo.ts_type = "number"
colInfo.sql_type = "float"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "bigint":
colInfo.ts_type = "number"
colInfo.sql_type = "bigint"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "date":
colInfo.ts_type = "Date"
colInfo.ts_type = "string"
colInfo.sql_type = "date"
break;
case "time":
colInfo.ts_type = "Date"
colInfo.ts_type = "string"
colInfo.sql_type = "time"
break;
case "datetime":
@ -113,13 +114,57 @@ export class MysqlDriver extends AbstractDriver {
colInfo.ts_type = "string"
colInfo.sql_type = "text"
break;
case "mediumint":
colInfo.ts_type = "number"
colInfo.sql_type = "mediumint"
break;
case "timestamp":
colInfo.ts_type = "Date"
colInfo.sql_type = "timestamp"
break;
case "year":
colInfo.ts_type = "number"
colInfo.sql_type = "year"
break;
case "blob":
colInfo.ts_type = "Buffer"
colInfo.sql_type = "blob"
break;
case "tinyblob":
colInfo.ts_type = "Buffer"
colInfo.sql_type = "tinyblob"
break;
case "tinytext":
colInfo.ts_type = "string"
colInfo.sql_type = "tinytext"
break;
case "mediumblob":
colInfo.ts_type = "Buffer"
colInfo.sql_type = "mediumblob"
break;
case "mediumtext":
colInfo.ts_type = "string"
colInfo.sql_type = "mediumtext"
break;
case "longblob":
colInfo.ts_type = "Buffer"
colInfo.sql_type = "longblob"
break;
case "longtext":
colInfo.ts_type = "string"
colInfo.sql_type = "longtext"
break;
case "varchar":
colInfo.ts_type = "string"
colInfo.sql_type = "string"
colInfo.sql_type = "varchar"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "nvarchar":
colInfo.ts_type = "string"
colInfo.sql_type = "string"
colInfo.sql_type = "nvarchar"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "money":
colInfo.ts_type = "number"
@ -128,32 +173,38 @@ export class MysqlDriver extends AbstractDriver {
case "real":
colInfo.ts_type = "number"
colInfo.sql_type = "double"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "double":
colInfo.ts_type = "number"
colInfo.sql_type = "double"
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "decimal":
colInfo.ts_type = "number"
colInfo.sql_type = "decimal"
colInfo.numericPrecision = resp.NUMERIC_PRECISION
colInfo.numericScale = resp.NUMERIC_SCALE
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
break;
case "xml":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
break;
case "json":
colInfo.ts_type = "Object"
colInfo.sql_type = "json"
break;
default:
console.error("Unknown column type:" + resp.DATA_TYPE);
break;
}
colInfo.char_max_lenght = resp.CHARACTER_MAXIMUM_LENGTH > 0 ? resp.CHARACTER_MAXIMUM_LENGTH : null;
if (colInfo.sql_type) ent.Columns.push(colInfo);
})
})
return entities;
}
async GetIndexesFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TableName: string, IndexName: string, ColumnName: string, is_unique: number,
is_primary_key: number//, is_descending_key: number//, is_included_column: number
@ -191,7 +242,7 @@ export class MysqlDriver extends AbstractDriver {
return entities;
}
async GetRelations(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response = await this.ExecQuery<{
TableWithForeignKey: string, FK_PartNo: number, ForeignKeyColumn: string,
TableReferenced: string, ForeignKeyColumnReferenced: string,
@ -278,18 +329,29 @@ export class MysqlDriver extends AbstractDriver {
isOneToMany = false;
}
let ownerRelation = new RelationInfo()
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length > 0) {
for (let i=2;i<=ownerEntity.Columns.length;i++){
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '') + i.toString();
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length == 0) break;
}
}
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
ownerRelation.isOwner = true
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
ownerRelation.relatedTable = relationTmp.referencedTable
ownerRelation.ownerTable = relationTmp.ownerTable
ownerRelation.ownerColumn = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
ownerRelation.ownerColumn = columnName
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
ownerColumn.relations.push(ownerRelation)
if (isOneToMany) {
let col = new ColumnInfo()
col.name = ownerEntity.EntityName.toLowerCase() + 's'
col.name = columnName
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
@ -303,7 +365,7 @@ export class MysqlDriver extends AbstractDriver {
referencedEntity.Columns.push(col)
} else {
let col = new ColumnInfo()
col.name = ownerEntity.EntityName.toLowerCase()
col.name = columnName
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionOnDelete = relationTmp.actionOnDelete
@ -329,7 +391,7 @@ export class MysqlDriver extends AbstractDriver {
resolve(true)
}
else {
console.error('Error disconnecting to MYSQL Server.')
console.error(`Error disconnecting to ${this.EngineName} Server.`)
console.error(err.message)
process.abort()
reject(err)
@ -343,14 +405,28 @@ export class MysqlDriver extends AbstractDriver {
}
private Connection: MYSQL.IConnection;
async ConnectToServer(database: string, server: string, port: number, user: string, password: string) {
let config: MYSQL.IConnectionConfig = {
database: database,
host: server,
port: port,
user: user,
password: password,
private Connection: MYSQL.Connection;
async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean) {
let config: MYSQL.ConnectionConfig
if (ssl) {
config = {
database: database,
host: server,
port: port,
user: user,
password: password,
ssl: {
rejectUnauthorized: false
}
}
} else {
config = {
database: database,
host: server,
port: port,
user: user,
password: password
}
}
@ -364,7 +440,7 @@ export class MysqlDriver extends AbstractDriver {
resolve(true)
}
else {
console.error('Error connecting to MYSQL Server.')
console.error(`Error connecting to ${this.EngineName} Server.`)
console.error(err.message)
process.abort()
reject(err)

View File

@ -23,10 +23,10 @@ export class PostgresDriver extends AbstractDriver {
});
}
async GetAllTables(): Promise<EntityInfo[]> {
async GetAllTables(schema: string): Promise<EntityInfo[]> {
let response: { table_schema: string, table_name: string }[]
= (await this.Connection.query("SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema = 'public' ")).rows;
= (await this.Connection.query(`SELECT table_schema,table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND table_schema = '${schema}' `)).rows;
let ret: EntityInfo[] = <EntityInfo[]>[];
response.forEach((val) => {
@ -38,7 +38,7 @@ export class PostgresDriver extends AbstractDriver {
})
return ret;
}
async GetCoulmnsFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetCoulmnsFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response: {
table_name: string, column_name: string, column_default: string,
is_nullable: string, data_type: string, character_maximum_length: number,
@ -46,9 +46,9 @@ export class PostgresDriver extends AbstractDriver {
}[]
= (await this.Connection.query(`SELECT table_name,column_name,column_default,is_nullable,
data_type,character_maximum_length,numeric_precision,numeric_scale
--,COLUMNPROPERTY(object_id(table_name), column_name, 'isidentity') isidentity
--,COLUMNPROPERTY(object_id(table_name), column_name, 'isidentity') isidentity
, case when column_default LIKE 'nextval%' then 'YES' else 'NO' end isidentity
FROM INFORMATION_SCHEMA.COLUMNS where table_schema ='public'`)).rows;
FROM INFORMATION_SCHEMA.COLUMNS where table_schema ='${schema}'`)).rows;
entities.forEach((ent) => {
response.filter((filterVal) => {
return filterVal.table_name == ent.EntityName;
@ -59,29 +59,33 @@ export class PostgresDriver extends AbstractDriver {
colInfo.is_generated = resp.isidentity == 'YES' ? true : false;
colInfo.default = colInfo.is_generated ? '' : resp.column_default;
switch (resp.data_type) {
//TODO:change types to postgres
case "integer":
colInfo.ts_type = "number"
colInfo.sql_type = "int"
break;
case "character varying":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
colInfo.sql_type = "varchar"
colInfo.char_max_lenght = resp.character_maximum_length > 0 ? resp.character_maximum_length : null;
break;
case "text":
colInfo.ts_type = "string"
colInfo.sql_type = "text"
break;
case "uuid":
colInfo.ts_type = "string"
colInfo.sql_type = "uuid"
break;
case "smallint":
colInfo.ts_type = "number"
colInfo.sql_type = "smallint"
break;
case "bigint":
colInfo.ts_type = "number"
colInfo.ts_type = "string"
colInfo.sql_type = "bigint"
break;
case "date":
colInfo.ts_type = "Date"
colInfo.ts_type = "string"
colInfo.sql_type = "date"
break;
case "boolean":
@ -91,71 +95,154 @@ export class PostgresDriver extends AbstractDriver {
case "double precision":
colInfo.ts_type = "number"
colInfo.sql_type = "double"
colInfo.numericPrecision = resp.numeric_precision
colInfo.numericScale = resp.numeric_scale
break;
case "real":
colInfo.ts_type = "number"
colInfo.sql_type = "float"
colInfo.numericPrecision = resp.numeric_precision
colInfo.numericScale = resp.numeric_scale
break;
case "numeric":
colInfo.ts_type = "number"
colInfo.sql_type = "decimal"
colInfo.ts_type = "string"
colInfo.sql_type = "numeric"
colInfo.numericPrecision = resp.numeric_precision
colInfo.numericScale = resp.numeric_scale
break;
case "time without time zone":
colInfo.ts_type = "Date"
colInfo.sql_type = "time"
colInfo.ts_type = "string"
colInfo.sql_type = "time without time zone"
break;
case "timestamp without time zone":
colInfo.ts_type = "Date"
colInfo.sql_type = "datetime"
break;
case "timestamp with time zone":
colInfo.ts_type = "Date"
colInfo.sql_type = "timestamp"
break;
case "json":
colInfo.ts_type = "any"
colInfo.ts_type = "Object"
colInfo.sql_type = "json"
break;
// case "boolean":
// colInfo.ts_type = "boolean"
// colInfo.sql_type = "boolean"
// break;
case "jsonb":
colInfo.ts_type = "Object"
colInfo.sql_type = "jsonb"
break;
case "money":
colInfo.ts_type = "string"
colInfo.sql_type = "money"
break;
case "character":
colInfo.ts_type = "string"
colInfo.sql_type = "character"
colInfo.char_max_lenght = resp.character_maximum_length > 0 ? resp.character_maximum_length : null;
break;
case "bytea":
colInfo.ts_type = "Buffer"
colInfo.sql_type = "bytea"
break;
case "interval":
colInfo.ts_type = "any"
colInfo.sql_type = "interval"
break;
case "time with time zone":
colInfo.ts_type = "string"
colInfo.sql_type = "time with time zone"
break;
case "point":
colInfo.ts_type = "string | Object"
colInfo.sql_type = "point"
break;
case "line":
colInfo.ts_type = "string"
colInfo.sql_type = "line"
break;
case "lseg":
colInfo.ts_type = "string | string[]"
colInfo.sql_type = "lseg"
break;
case "box":
colInfo.ts_type = "string | Object"
colInfo.sql_type = "box"
break;
case "path":
colInfo.ts_type = "string"
colInfo.sql_type = "path"
break;
case "polygon":
colInfo.ts_type = "string"
colInfo.sql_type = "polygon"
break;
case "circle":
colInfo.ts_type = "string | Object"
colInfo.sql_type = "circle"
break;
case "cidr":
colInfo.ts_type = "string"
colInfo.sql_type = "cidr"
break;
case "inet":
colInfo.ts_type = "string"
colInfo.sql_type = "inet"
break;
case "macaddr":
colInfo.ts_type = "string"
colInfo.sql_type = "macaddr"
break;
case "bit":
colInfo.ts_type = "string"
colInfo.sql_type = "bit"
break;
case "bit varying":
colInfo.ts_type = "string"
colInfo.sql_type = "bit varying"
break;
case "xml":
colInfo.ts_type = "string"
colInfo.sql_type = "xml"
break;
default:
console.error("Unknown column type:" + resp.data_type);
break;
}
colInfo.char_max_lenght = resp.character_maximum_length > 0 ? resp.character_maximum_length : null;
if (colInfo.sql_type) ent.Columns.push(colInfo);
})
})
return entities;
}
async GetIndexesFromEntity(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetIndexesFromEntity(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response: {
tablename: string, indexname: string, columnname: string, is_unique: number,
is_primary_key: number//, is_descending_key: number//, is_included_column: number
}[]
= (await this.Connection.query(`SELECT
= (await this.Connection.query(`SELECT
c.relname AS tablename,
i.relname as indexname,
f.attname AS columnname,
CASE
WHEN ix.indisunique = true THEN '1'
i.relname as indexname,
f.attname AS columnname,
CASE
WHEN ix.indisunique = true THEN '1'
ELSE '0'
END AS is_unique,
CASE
WHEN p.contype = 'p' THEN '1'
ELSE '0'
END AS is_unique,
CASE
WHEN p.contype = 'p' THEN '1'
ELSE '0'
END AS is_primary_key
FROM pg_attribute f
JOIN pg_class c ON c.oid = f.attrelid
JOIN pg_type t ON t.oid = f.atttypid
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
FROM pg_attribute f
JOIN pg_class c ON c.oid = f.attrelid
JOIN pg_type t ON t.oid = f.atttypid
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
LEFT JOIN pg_class AS g ON p.confrelid = g.oid
LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid
LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid
WHERE c.relkind = 'r'::char
AND n.nspname = 'public' -- Replace with Schema name
LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) and c.oid = f.attrelid and c.oid = ix.indrelid
LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid
WHERE c.relkind = 'r'::char
AND n.nspname = '${schema}'
--AND c.relname = 'nodes' -- Replace with table name, or Comment this for get all tables
AND f.attnum > 0
AND i.oid<>0
@ -192,14 +279,14 @@ export class PostgresDriver extends AbstractDriver {
return entities;
}
async GetRelations(entities: EntityInfo[]): Promise<EntityInfo[]> {
async GetRelations(entities: EntityInfo[], schema: string): Promise<EntityInfo[]> {
let response: {
tablewithforeignkey: string, fk_partno: number, foreignkeycolumn: string,
tablereferenced: string, foreignkeycolumnreferenced: string,
ondelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION",
onupdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION", object_id: string
}[]
= (await this.Connection.query(`SELECT
= (await this.Connection.query(`SELECT
con.relname AS tablewithforeignkey,
att.attnum as fk_partno,
att2.attname AS foreignkeycolumn,
@ -208,32 +295,33 @@ export class PostgresDriver extends AbstractDriver {
update_rule as ondelete,
delete_rule as onupdate,
con.conname as object_id
FROM (
SELECT
FROM (
SELECT
unnest(con1.conkey) AS parent,
unnest(con1.confkey) AS child,
con1.confrelid,
con1.conrelid,
cl_1.relname,
con1.conname
FROM
FROM
pg_class cl_1,
pg_namespace ns,
pg_constraint con1
WHERE
con1.contype = 'f'::"char"
AND cl_1.relnamespace = ns.oid
WHERE
con1.contype = 'f'::"char"
AND cl_1.relnamespace = ns.oid
AND con1.conrelid = cl_1.oid
and nspname='${schema}'
) con,
pg_attribute att,
pg_class cl,
pg_attribute att2,
information_schema.referential_constraints rc
WHERE
att.attrelid = con.confrelid
AND att.attnum = con.child
WHERE
att.attrelid = con.confrelid
AND att.attnum = con.child
AND cl.oid = con.confrelid
AND att2.attrelid = con.conrelid
AND att2.attrelid = con.conrelid
AND att2.attnum = con.parent
and rc.constraint_name= con.conname`)).rows;
let relationsTemp: RelationTempInfo[] = <RelationTempInfo[]>[];
@ -300,18 +388,29 @@ export class PostgresDriver extends AbstractDriver {
isOneToMany = false;
}
let ownerRelation = new RelationInfo()
let columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length>0){
for (let i=2;i<=ownerEntity.Columns.length;i++){
columnName = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')+i.toString();
if (referencedEntity.Columns.filter((filterVal) => {
return filterVal.name == columnName;
}).length==0) break;
}
}
ownerRelation.actionOnDelete = relationTmp.actionOnDelete
ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate
ownerRelation.isOwner = true
ownerRelation.relatedColumn = relatedColumn.name.toLowerCase()
ownerRelation.relatedTable = relationTmp.referencedTable
ownerRelation.ownerTable = relationTmp.ownerTable
ownerRelation.ownerColumn = ownerEntity.EntityName.toLowerCase() + (isOneToMany ? 's' : '')
ownerRelation.ownerColumn = columnName
ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"
ownerColumn.relations.push(ownerRelation)
if (isOneToMany) {
let col = new ColumnInfo()
col.name = ownerEntity.EntityName.toLowerCase() + 's'
col.name = columnName
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionondelete = relationTmp.actionOnDelete
@ -325,7 +424,7 @@ export class PostgresDriver extends AbstractDriver {
referencedEntity.Columns.push(col)
} else {
let col = new ColumnInfo()
col.name = ownerEntity.EntityName.toLowerCase()
col.name = columnName
let referencedRelation = new RelationInfo();
col.relations.push(referencedRelation)
referencedRelation.actionondelete = relationTmp.actionOnDelete
@ -363,13 +462,14 @@ export class PostgresDriver extends AbstractDriver {
}
}
async ConnectToServer(database: string, server: string, port: number, user: string, password: string) {
async ConnectToServer(database: string, server: string, port: number, user: string, password: string, ssl: boolean) {
this.Connection = new PG.Client({
database: database,
host: server,
port: port,
user: user,
password: password
password: password,
ssl: ssl
})

View File

@ -22,7 +22,7 @@ import {{curly true}}{{toEntityName this}}{{curly false}} from "./{{toFileName t
{{/relations~}}
{{~#relations}} @{{relationType}}(type => {{toEntityName relatedTable}}, {{toPropertyName ../name}} => {{toPropertyName ../name}}.{{#if isOwner}}{{toPropertyName ownerColumn}}{{else}}{{toPropertyName relatedColumn}}{{/if}}){{#isOwner}}
@JoinColumn(){{/isOwner}}
@JoinColumn({name: "{{../name}}"}){{/isOwner}}
{{#if isOneToMany}}{{toPropertyName ../name}}: {{toEntityName relatedTable}}[];{{else}}{{toPropertyName ../name}}: {{toEntityName relatedTable}};{{/if}}
{{/relations~}}
{{"\n"}}

View File

@ -29,7 +29,7 @@ var argv = Yargs
.option('x', {
alias: 'pass',
describe: 'Password for database server.',
demand: true
default: ''
})
.option('p', {
alias: 'port',
@ -46,6 +46,14 @@ var argv = Yargs
describe: 'Where to place generated models.',
default: path.resolve(process.cwd(), 'output')
})
.option('s', {
alias: 'schema',
describe: 'Schema name to create model from. Only for mssql and postgres.'
})
.option('ssl',{
boolean:true,
default:false
})
.option('c', {
alias: 'case',
describe: 'Convert snake_case tables names to PascalCase entities and snake_case columns to camelCase properties'
@ -55,14 +63,17 @@ var argv = Yargs
var driver: AbstractDriver;
var standardPort: number;
var standardSchema: string = '';
switch (argv.e) {
case 'mssql':
driver = new MssqlDriver();
standardPort = 1433;
standardSchema = 'dbo';
break;
case 'postgres':
driver = new PostgresDriver();
standardPort = 5432;
standardSchema = 'public';
break;
case 'mysql':
driver = new MysqlDriver();
@ -87,6 +98,8 @@ let engine = new Engine(
password: argv.x,
databaseType: argv.e,
resultsPath: argv.o,
schemaName: argv.s || standardSchema,
ssl:argv.ssl,
convertCase: !!argv.c
});

View File

@ -1,4 +1,5 @@
import { RelationInfo } from './RelationInfo'
import { ColumnType } from 'typeorm';
/**
* ColumnInfo
*/
@ -6,9 +7,8 @@ export class ColumnInfo {
name: string = '';
default: string | null = null;
is_nullable: boolean = false;
ts_type: 'number' | 'string' | 'boolean' | 'Date' | 'any';
sql_type: "string" | "text" | "number" | "integer" | "int" | "smallint" | "bigint" |
"float" | "double" | "decimal" | "date" | "time" | "datetime" | "boolean" | "json";
ts_type: 'number' | 'string' | 'boolean' | 'Date' | 'Buffer' | 'Object' | 'string | Object' | 'string | string[]' | 'any';
sql_type: ColumnType;
char_max_lenght: number | null = null;
isPrimary: boolean = false;
is_generated: boolean = false;

View File

@ -5,7 +5,21 @@ import * as MSSQL from 'mssql'
import { EntityInfo } from './../../src/models/EntityInfo'
import { ColumnInfo } from './../../src/models/ColumnInfo'
import { RelationInfo } from './../../src/models/RelationInfo'
import { Table, IColumnMetadata } from "mssql";
class fakeResponse implements MSSQL.IResult<any> {
recordsets: MSSQL.IRecordSet<any>[];
recordset: MSSQL.IRecordSet<any>;
rowsAffected: number[];
output: { [key: string]: any; };
}
class fakeRecordset extends Array<any> implements MSSQL.IRecordSet<any>{
columns: IColumnMetadata;
toTable(): Table{
return new Table();
}
}
describe('MssqlDriver', function () {
let driver: MssqlDriver
@ -34,13 +48,16 @@ describe('MssqlDriver', function () {
.returns(
{
query: (q) => {
let response = <{ TABLE_SCHEMA: string, TABLE_NAME: string }[]>[];
response.push({ TABLE_SCHEMA: 'schema', TABLE_NAME: 'name' })
let response=new fakeResponse();
response.recordset=new fakeRecordset();
response.recordset.push({ TABLE_SCHEMA: 'schema', TABLE_NAME: 'name' })
return response;
}
}
)
let result = await driver.GetAllTables()
let result = await driver.GetAllTables('schema')
let expectedResult = <EntityInfo[]>[];
let y = new EntityInfo();
y.EntityName = 'name'
@ -54,12 +71,9 @@ describe('MssqlDriver', function () {
.returns(
{
query: (q) => {
let response = <{
TABLE_NAME: string, COLUMN_NAME: string, COLUMN_DEFAULT: string,
IS_NULLABLE: string, DATA_TYPE: string, CHARACTER_MAXIMUM_LENGTH: number,
NUMERIC_PRECISION: number, NUMERIC_SCALE: number, IsIdentity:number
}[]>[]
response.push({
let response=new fakeResponse();
response.recordset=new fakeRecordset();
response.recordset.push({
TABLE_NAME: 'name', CHARACTER_MAXIMUM_LENGTH: 0,
COLUMN_DEFAULT: 'a', COLUMN_NAME: 'name', DATA_TYPE: 'int',
IS_NULLABLE: 'YES', NUMERIC_PRECISION: 0, NUMERIC_SCALE: 0,
@ -91,7 +105,7 @@ describe('MssqlDriver', function () {
ts_type: 'number',
relations: <RelationInfo[]>[]
})
let result = await driver.GetCoulmnsFromEntity(entities);
let result = await driver.GetCoulmnsFromEntity(entities,'schema');
expect(result).to.be.deep.equal(expected)
})
it('should find primary indexes')

View File

@ -0,0 +1,99 @@
require('dotenv').config()
import "reflect-metadata";
import { createConnection, ConnectionOptions, Connection } from "typeorm";
import fs = require('fs-extra');
import path = require('path')
import { expect } from "chai";
import * as Sinon from 'sinon'
import { EntityFileToJson } from "../utils/EntityFileToJson";
var chai = require('chai');
var chaiSubset = require('chai-subset');
import * as ts from "typescript";
import * as GTU from "../utils/GeneralTestUtils"
import { Engine } from "./../../src/Engine";
chai.use(chaiSubset);
describe("Platform specyfic types", async function () {
this.timeout(20000)
this.slow(5000)//compiling created models takes time
let dbDrivers: string[] = []
if (process.env.POSTGRES_Skip == '0') dbDrivers.push('postgres')
if (process.env.MYSQL_Skip == '0') dbDrivers.push('mysql')
if (process.env.MARIADB_Skip == '0') dbDrivers.push('mariadb')
if (process.env.MSSQL_Skip == '0') dbDrivers.push('mssql')
let examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/entityTypes')
let examplesPathTS = path.resolve(process.cwd(), 'test/integration/entityTypes')
let files = fs.readdirSync(examplesPathTS)
for (let folder of files) {
for (let dbDriver of dbDrivers) {
if (dbDriver == folder) {
it(dbDriver, async function () {
let filesOrgPathJS = path.resolve(examplesPathJS, folder, 'entity')
let filesOrgPathTS = path.resolve(examplesPathTS, folder, 'entity')
let resultsPath = path.resolve(process.cwd(), `output`)
fs.removeSync(resultsPath)
let engine: Engine;
switch (dbDriver) {
case 'mssql':
engine = await GTU.createMSSQLModels(filesOrgPathJS, resultsPath)
break;
case 'postgres':
engine = await GTU.createPostgresModels(filesOrgPathJS, resultsPath)
break;
case 'mysql':
engine = await GTU.createMysqlModels(filesOrgPathJS, resultsPath)
break;
case 'mariadb':
engine = await GTU.createMariaDBModels(filesOrgPathJS, resultsPath)
break;
default:
console.log(`Unknown engine type`);
engine = <Engine>{}
break;
}
let result = await engine.createModelFromDatabase()
let filesGenPath = path.resolve(resultsPath, 'entities')
let filesOrg = fs.readdirSync(filesOrgPathTS).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') })
let filesGen = fs.readdirSync(filesGenPath).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') })
expect(filesOrg, 'Errors detected in model comparision').to.be.deep.equal(filesGen)
for (let file of filesOrg) {
let entftj = new EntityFileToJson();
let jsonEntityOrg = entftj.convert(fs.readFileSync(path.resolve(filesOrgPathTS, file)))
let jsonEntityGen = entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
expect(jsonEntityGen, `Error in file ${file}`).to.containSubset(jsonEntityOrg)
}
const currentDirectoryFiles = fs.readdirSync(filesGenPath).
filter(fileName => fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts").map(v => {
return path.resolve(filesGenPath, v)
})
let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
experimentalDecorators: true,
sourceMap: false,
emitDecoratorMetadata: true,
target: ts.ScriptTarget.ES2016,
moduleResolution: ts.ModuleResolutionKind.NodeJs,
module: ts.ModuleKind.CommonJS
});
expect(compileErrors, 'Errors detected while compiling generated model').to.be.false;
});
}
}
}
})

View File

@ -0,0 +1,94 @@
import { Entity, PrimaryColumn, Column } from "typeorm";
@Entity("Post")
export class Post {
@PrimaryColumn()
id: number;
@Column()
name: string;
@Column("int")
int: number;
@Column("tinyint")
tinyint: number;
@Column("smallint")
smallint: number;
@Column("mediumint")
mediumint: number;
@Column("bigint")
bigint: number;
@Column("float")
float: number;
@Column("double")
double: number;
@Column("decimal")
decimal: number;
@Column("date")
date: string;
@Column("datetime")
datetime: Date;
@Column("timestamp")
timestamp: Date;
@Column("time")
time: string;
@Column("year")
year: number;
@Column("char")
char: string;
@Column("varchar")
varchar: string;
@Column("blob")
blob: Buffer;
@Column("text")
text: string;
@Column("tinyblob")
tinyblob: Buffer;
@Column("tinytext")
tinytext: string;
@Column("mediumblob")
mediumblob: Buffer;
@Column("mediumtext")
mediumtext: string;
@Column("longblob")
longblob: Buffer;
@Column("longtext")
longtext: string;
// @Column("enum", { enum: ["A", "B", "C"] })
// enum: string;
// @Column("enum", { enum: FruitEnum })
// classEnum1: FruitEnum;
//MariaDb type for Json - LONGTEXT
// @Column("json")
// json: Object;
// @Column("simple-array")
// simpleArray: string[];
}

View File

@ -0,0 +1,121 @@
import { Entity, PrimaryColumn, Column } from "typeorm";
@Entity("Post")
export class Post {
@PrimaryColumn()
id: number;
@Column()
name: string;
// -------------------------------------------------------------------------
// Numeric Types
// -------------------------------------------------------------------------
@Column("bit")
bit: boolean;
@Column("tinyint")
tinyint: number;
@Column("smallint")
smallint: number;
@Column("int")
int: number;
@Column("bigint")
bigint: string;
@Column("decimal")
decimal: number;
@Column("dec")
dec: number;
@Column("numeric")
numeric: number;
@Column("float")
float: number;
@Column("real")
real: number;
@Column("smallmoney")
smallmoney: number;
@Column("money")
money: number;
// -------------------------------------------------------------------------
// Character Types
// -------------------------------------------------------------------------
@Column("uniqueidentifier")
uniqueidentifier: string;
@Column("char")
char: string;
@Column("varchar")
varchar: string;
@Column("text")
text: string;
@Column("nchar")
nchar: string;
@Column("nvarchar")
nvarchar: string;
@Column("ntext")
ntext: string;
@Column("binary")
binary: Buffer;
@Column("varbinary")
varbinary: Buffer;
@Column("image")
image: Buffer;
// -------------------------------------------------------------------------
// Date Types
// -------------------------------------------------------------------------
@Column("date")
dateObj: Date;
// @Column("date")
// date: string;
@Column("datetime")
datetime: Date;
@Column("datetime2")
datetime2: Date;
@Column("smalldatetime")
smalldatetime: Date;
@Column("time")
timeObj: Date;
// @Column("time")
// time: string;
@Column("datetimeoffset")
datetimeoffset: Date;
// -------------------------------------------------------------------------
// TypeOrm Specific Type
// -------------------------------------------------------------------------
// @Column("simple-array")
// simpleArray: string[];
}

View File

@ -0,0 +1,93 @@
import { Entity, PrimaryColumn, Column } from "typeorm";
@Entity("Post")
export class Post {
@PrimaryColumn()
id: number;
@Column()
name: string;
@Column("int")
int: number;
@Column("tinyint")
tinyint: number;
@Column("smallint")
smallint: number;
@Column("mediumint")
mediumint: number;
@Column("bigint")
bigint: number;
@Column("float")
float: number;
@Column("double")
double: number;
@Column("decimal")
decimal: number;
@Column("date")
date: string;
@Column("datetime")
datetime: Date;
@Column("timestamp")
timestamp: Date;
@Column("time")
time: string;
@Column("year")
year: number;
@Column("char")
char: string;
@Column("varchar")
varchar: string;
@Column("blob")
blob: Buffer;
@Column("text")
text: string;
@Column("tinyblob")
tinyblob: Buffer;
@Column("tinytext")
tinytext: string;
@Column("mediumblob")
mediumblob: Buffer;
@Column("mediumtext")
mediumtext: string;
@Column("longblob")
longblob: Buffer;
@Column("longtext")
longtext: string;
// @Column("enum", { enum: ["A", "B", "C"] })
// enum: string;
// @Column("enum", { enum: FruitEnum })
// classEnum1: FruitEnum;
@Column("json")
json: Object;
// @Column("simple-array")
// simpleArray: string[];
}

View File

@ -0,0 +1,240 @@
import { Entity, PrimaryColumn, Column } from "typeorm";
@Entity("Post")
export class Post {
@PrimaryColumn()
id: number;
@Column()
name: string;
// -------------------------------------------------------------------------
// Numeric Types
// -------------------------------------------------------------------------
@Column("integer")
integer: number;
@Column("int4")
int4: number;
@Column("int")
int: number;
@Column("smallint")
smallint: number;
@Column("int2")
int2: number;
@Column("bigint")
bigint: string;
@Column("int8")
int8: string;
// @Column("serial")
// serial: number;
// @Column("serial4")
// serial4: number;
// @Column("smallserial")
// smallserial: number;
// @Column("serial2")
// serial2: number;
// @Column("bigserial")
// bigserial: number;
// @Column("serial8")
// serial8: number;
@Column("numeric")
numeric: string;
@Column("decimal")
decimal: string;
@Column("double precision")
doublePrecision: number;
@Column("float8")
float8: number;
@Column("real")
real: number;
@Column("float4")
float4: number;
// -------------------------------------------------------------------------
// Monetary Types
// -------------------------------------------------------------------------
@Column("money")
money: string;
// -------------------------------------------------------------------------
// Character Types
// -------------------------------------------------------------------------
@Column("char")
char: string;
@Column("character")
character: string;
@Column("varchar")
varchar: string;
@Column("character varying")
characterVarying: string;
@Column("text")
text: string;
// @Column("citext")
// citext: string;
// -------------------------------------------------------------------------
// Binary Data Types
// -------------------------------------------------------------------------
@Column("bytea")
bytea: Buffer;
// -------------------------------------------------------------------------
// Date/Time Types
// -------------------------------------------------------------------------
@Column("date")
date: string;
@Column("interval")
interval: any;
@Column("time")
time: string;
@Column("time with time zone")
timeWithTimeZone: string;
@Column("timetz")
timetz: string;
@Column("timestamp")
timestamp: Date;
@Column("timestamp with time zone")
timestampWithTimeZone: Date;
@Column("timestamptz")
timestamptz: Date;
// -------------------------------------------------------------------------
// Boolean Type
// -------------------------------------------------------------------------
@Column("boolean")
boolean: boolean;
@Column("bool")
bool: boolean;
// -------------------------------------------------------------------------
// Enumerated Type
// -------------------------------------------------------------------------
// @Column("enum", { enum: ["A", "B", "C"] })
// enum: string;
// -------------------------------------------------------------------------
// Geometric Type
// -------------------------------------------------------------------------
@Column("point")
point: string | Object;
@Column("line")
line: string;
@Column("lseg")
lseg: string | string[];
@Column("box")
box: string | Object;
@Column("path")
path: string;
@Column("polygon")
polygon: string;
@Column("circle")
circle: string | Object;
// -------------------------------------------------------------------------
// Network Address Type
// -------------------------------------------------------------------------
@Column("cidr")
cidr: string;
@Column("inet")
inet: string;
@Column("macaddr")
macaddr: string;
// -------------------------------------------------------------------------
// Bit String Type
// -------------------------------------------------------------------------
@Column("bit")
bit: string;
@Column("varbit")
varbit: string;
@Column("bit varying")
bitVarying: string;
// -------------------------------------------------------------------------
// UUID Type
// -------------------------------------------------------------------------
@Column("uuid")
uuid: string;
// -------------------------------------------------------------------------
// XML Type
// -------------------------------------------------------------------------
@Column("xml")
xml: string;
// -------------------------------------------------------------------------
// JSON Type
// -------------------------------------------------------------------------
@Column("json")
json: Object;
// -------------------------------------------------------------------------
// Array Type
// -------------------------------------------------------------------------
// @Column("int", { isArray: true })
// array: number[];
// // -------------------------------------------------------------------------
// // TypeOrm Specific Type
// // -------------------------------------------------------------------------
// @Column("simple-array")
// simpleArray: string[];
}

View File

@ -1,9 +1,9 @@
import {Column, Entity,PrimaryColumn,Index} from "typeorm";
import {Column, Entity,PrimaryGeneratedColumn,Index,Generated} from "typeorm";
@Entity("Post")
export class Post {
@PrimaryColumn("int", { generated: true })
@PrimaryGeneratedColumn()
id: number;
@Column()

View File

@ -2,7 +2,7 @@ import { PrimaryGeneratedColumn, Column, Entity, OneToOne, JoinColumn, Index } f
@Entity("EverythingEntity")
export class EverythingEntity {
//TODO: change to check column types per database engine
@PrimaryGeneratedColumn()
id: number;
@ -27,35 +27,35 @@ export class EverythingEntity {
@Column("smallint")
smallintColumn: number;
@Column("bigint")
bigintColumn: number;
// @Column("bigint")
// bigintColumn: number;
@Column("float")
floatColumn: number;
// @Column("float")
// floatColumn: number;
@Column("double")
doubleColumn: number;
// @Column("double")
// doubleColumn: number;
@Column("decimal")
decimalColumn: number;
// @Column("decimal")
// decimalColumn: number;
@Column()
date: Date;
@Column("date")
dateColumn: Date;
// @Column("date")
// dateColumn: Date;
@Column("time")
timeColumn: Date;
// @Column("time")
// timeColumn: Date;
@Column("boolean")
isBooleanColumn: boolean;
// @Column("boolean")
// isBooleanColumn: boolean;
@Column("boolean")
isSecondBooleanColumn: boolean;
// @Column("boolean")
// isSecondBooleanColumn: boolean;
@Column("json")
jsonColumn: any;
// @Column("json")
// jsonColumn: any;
// @Column()
// alsoJson: any;

View File

@ -0,0 +1,16 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm";
import { PostAuthor } from "./PostAuthor";
@Entity("Post")
export class Post {
@PrimaryGeneratedColumn()
id: number;
@ManyToOne(type => PostAuthor, author => author.posts)
author: PostAuthor;
@ManyToOne(type => PostAuthor, author => author.posts2)
author2: PostAuthor;
}

View File

@ -0,0 +1,16 @@
import { PrimaryGeneratedColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, JoinColumn } from "typeorm";
import { Post } from "./Post";
@Entity("PostAuthor")
export class PostAuthor {
@PrimaryGeneratedColumn()
id: number;
@OneToMany(type => Post, post => post.author)
posts: Post[];
@OneToMany(type => Post, post => post.author2)
posts2: Post[];
}

View File

@ -0,0 +1,100 @@
require('dotenv').config()
import "reflect-metadata";
import { createConnection, ConnectionOptions, Connection } from "typeorm";
import fs = require('fs-extra');
import path = require('path')
import { Engine } from "./../../src/Engine";
import { expect } from "chai";
import * as Sinon from 'sinon'
import { EntityFileToJson } from "../utils/EntityFileToJson";
var chai = require('chai');
var chaiSubset = require('chai-subset');
import * as yn from "yn"
import * as ts from "typescript";
import * as GTU from "../utils/GeneralTestUtils"
chai.use(chaiSubset);
describe("GitHub issues", async function () {
this.timeout(20000)
this.slow(5000)//compiling created models takes time
let dbDrivers: string[] = []
if (process.env.POSTGRES_Skip == '0') dbDrivers.push('postgres')
if (process.env.MYSQL_Skip == '0') dbDrivers.push('mysql')
if (process.env.MARIADB_Skip == '0') dbDrivers.push('mariadb')
if (process.env.MSSQL_Skip == '0') dbDrivers.push('mssql')
let examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/github-issues')
let examplesPathTS = path.resolve(process.cwd(), 'test/integration/github-issues')
let files = fs.readdirSync(examplesPathTS)
for (let folder of files) {
describe(`#${folder}`, async function () {
for (let dbDriver of dbDrivers) {
it(dbDriver, async function () {
let filesOrgPathJS = path.resolve(examplesPathJS, folder, 'entity')
let filesOrgPathTS = path.resolve(examplesPathTS, folder, 'entity')
let resultsPath = path.resolve(process.cwd(), `output`)
fs.removeSync(resultsPath)
let engine: Engine;
switch (dbDriver) {
case 'mssql':
engine = await GTU.createMSSQLModels(filesOrgPathJS, resultsPath)
break;
case 'postgres':
engine = await GTU.createPostgresModels(filesOrgPathJS, resultsPath)
break;
case 'mysql':
engine = await GTU.createMysqlModels(filesOrgPathJS, resultsPath)
break;
case 'mariadb':
engine = await GTU.createMariaDBModels(filesOrgPathJS, resultsPath)
break;
default:
console.log(`Unknown engine type`);
engine = <Engine>{}
break;
}
let result = await engine.createModelFromDatabase()
let filesGenPath = path.resolve(resultsPath, 'entities')
let filesOrg = fs.readdirSync(filesOrgPathTS).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') })
let filesGen = fs.readdirSync(filesGenPath).filter(function (this, val, ind, arr) { return val.toString().endsWith('.ts') })
expect(filesOrg, 'Errors detected in model comparision').to.be.deep.equal(filesGen)
for (let file of filesOrg) {
let entftj = new EntityFileToJson();
let jsonEntityOrg = entftj.convert(fs.readFileSync(path.resolve(filesOrgPathTS, file)))
let jsonEntityGen = entftj.convert(fs.readFileSync(path.resolve(filesGenPath, file)))
expect(jsonEntityGen, `Error in file ${file}`).to.containSubset(jsonEntityOrg)
}
const currentDirectoryFiles = fs.readdirSync(filesGenPath).
filter(fileName => fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts").map(v => {
return path.resolve(filesGenPath, v)
})
let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
experimentalDecorators: true,
sourceMap: false,
emitDecoratorMetadata: true,
target: ts.ScriptTarget.ES2016,
moduleResolution: ts.ModuleResolutionKind.NodeJs,
module: ts.ModuleKind.CommonJS
});
expect(compileErrors, 'Errors detected while compiling generated model').to.be.false;
});
}
})
}
})

View File

@ -4,36 +4,32 @@ import { createConnection, ConnectionOptions, Connection } from "typeorm";
import fs = require('fs-extra');
import path = require('path')
import { Engine } from "./../../src/Engine";
import { AbstractDriver } from "./../../src/drivers/AbstractDriver";
import { MssqlDriver } from "./../../src/drivers/MssqlDriver";
import { DriverType } from "typeorm/driver/DriverOptions";
import { expect } from "chai";
import * as Sinon from 'sinon'
import { EntityFileToJson } from "../utils/EntityFileToJson";
var chai = require('chai');
var chaiSubset = require('chai-subset');
import * as yn from "yn"
import * as ts from "typescript";
import { PostgresDriver } from "../../src/drivers/PostgresDriver";
import { MysqlDriver } from "../../src/drivers/MysqlDriver";
import { MariaDbDriver } from "../../src/drivers/MariaDbDriver";
import * as GTU from "../utils/GeneralTestUtils"
chai.use(chaiSubset);
describe("integration tests", async function () {
describe("TypeOrm examples", async function () {
this.timeout(20000)
this.slow(5000)//compiling created models takes time
let examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/examples')
let examplesPathTS = path.resolve(process.cwd(), 'test/integration/examples')
let files = fs.readdirSync(examplesPathTS)
let dbDrivers: DriverType[] = []
let dbDrivers: string[] = []
if (process.env.POSTGRES_Skip == '0') dbDrivers.push('postgres')
if (process.env.MYSQL_Skip == '0') dbDrivers.push('mysql')
if (process.env.MARIADB_Skip == '0') dbDrivers.push('mariadb')
if (process.env.MSSQL_Skip == '0') dbDrivers.push('mssql')
let examplesPathJS = path.resolve(process.cwd(), 'dist/test/integration/examples')
let examplesPathTS = path.resolve(process.cwd(), 'test/integration/examples')
let files = fs.readdirSync(examplesPathTS)
for (let folder of files) {
describe(folder, async function () {
@ -48,16 +44,16 @@ describe("integration tests", async function () {
let engine: Engine;
switch (dbDriver) {
case 'mssql':
engine = await createMSSQLModels(filesOrgPathJS, resultsPath)
engine = await GTU.createMSSQLModels(filesOrgPathJS, resultsPath)
break;
case 'postgres':
engine = await createPostgresModels(filesOrgPathJS, resultsPath)
engine = await GTU.createPostgresModels(filesOrgPathJS, resultsPath)
break;
case 'mysql':
engine = await createMysqlModels(filesOrgPathJS, resultsPath)
engine = await GTU.createMysqlModels(filesOrgPathJS, resultsPath)
break;
case 'mariadb':
engine = await createMariaDBModels(filesOrgPathJS, resultsPath)
engine = await GTU.createMariaDBModels(filesOrgPathJS, resultsPath)
break;
default:
@ -86,7 +82,7 @@ describe("integration tests", async function () {
filter(fileName => fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts").map(v => {
return path.resolve(filesGenPath, v)
})
let compileErrors = compileTsFiles(currentDirectoryFiles, {
let compileErrors = GTU.compileTsFiles(currentDirectoryFiles, {
experimentalDecorators: true,
sourceMap: false,
@ -102,199 +98,3 @@ describe("integration tests", async function () {
})
}
})
async function createMSSQLModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new MssqlDriver();
await driver.ConnectToServer(`master`, process.env.MSSQL_Host, process.env.MSSQL_Port, process.env.MSSQL_Username, process.env.MSSQL_Password);
if (! await driver.CheckIfDBExists(process.env.MSSQL_Database))
await driver.CreateDB(process.env.MSSQL_Database);
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
driver: {
database: process.env.MSSQL_Database,
host: process.env.MSSQL_Host,
password: process.env.MSSQL_Password,
type: 'mssql',
username: process.env.MSSQL_Username,
port: process.env.MSSQL_Port
},
dropSchemaOnConnection: true,
autoSchemaSync: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new MssqlDriver();
let engine = new Engine(
driver, {
host: process.env.MSSQL_Host,
port: process.env.MSSQL_Port,
databaseName: process.env.MSSQL_Database,
user: process.env.MSSQL_Username,
password: process.env.MSSQL_Password,
databaseType: 'mssql',
resultsPath: resultsPath,
convertCase: true
});
return engine;
}
async function createPostgresModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new PostgresDriver();
await driver.ConnectToServer(`postgres`, process.env.POSTGRES_Host, process.env.POSTGRES_Port, process.env.POSTGRES_Username, process.env.POSTGRES_Password);
if (! await driver.CheckIfDBExists(process.env.POSTGRES_Database))
await driver.CreateDB(process.env.POSTGRES_Database);
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
driver: {
database: process.env.POSTGRES_Database,
host: process.env.POSTGRES_Host,
password: process.env.POSTGRES_Password,
type: 'postgres',
username: process.env.POSTGRES_Username,
port: process.env.POSTGRES_Port
},
dropSchemaOnConnection: true,
autoSchemaSync: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new PostgresDriver();
let engine = new Engine(
driver, {
host: process.env.POSTGRES_Host,
port: process.env.POSTGRES_Port,
databaseName: process.env.POSTGRES_Database,
user: process.env.POSTGRES_Username,
password: process.env.POSTGRES_Password,
databaseType: 'postgres',
resultsPath: resultsPath,
convertCase: true
});
return engine;
}
async function createMysqlModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new MysqlDriver();
await driver.ConnectToServer(`mysql`, process.env.MYSQL_Host, process.env.MYSQL_Port, process.env.MYSQL_Username, process.env.MYSQL_Password);
if (! await driver.CheckIfDBExists(process.env.MYSQL_Database))
await driver.CreateDB(process.env.MYSQL_Database);
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
driver: {
database: process.env.MYSQL_Database,
host: process.env.MYSQL_Host,
password: process.env.MYSQL_Password,
type: 'mysql',
username: process.env.MYSQL_Username,
port: process.env.MYSQL_Port
},
dropSchemaOnConnection: true,
autoSchemaSync: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new MysqlDriver();
let engine = new Engine(
driver, {
host: process.env.MYSQL_Host,
port: process.env.MYSQL_Port,
databaseName: process.env.MYSQL_Database,
user: process.env.MYSQL_Username,
password: process.env.MYSQL_Password,
databaseType: 'mysql',
resultsPath: resultsPath,
convertCase: true
});
return engine;
}
async function createMariaDBModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new MariaDbDriver();
await driver.ConnectToServer(`mysql`, process.env.MARIADB_Host, process.env.MARIADB_Port, process.env.MARIADB_Username, process.env.MARIADB_Password);
if (! await driver.CheckIfDBExists(process.env.MARIADB_Database))
await driver.CreateDB(process.env.MARIADB_Database);
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
driver: {
database: process.env.MARIADB_Database,
host: process.env.MARIADB_Host,
password: process.env.MARIADB_Password,
type: 'mariadb',
username: process.env.MARIADB_Username,
port: process.env.MARIADB_Port
},
dropSchemaOnConnection: true,
autoSchemaSync: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new MariaDbDriver();
let engine = new Engine(
driver, {
host: process.env.MARIADB_Host,
port: process.env.MARIADB_Port,
databaseName: process.env.MARIADB_Database,
user: process.env.MARIADB_Username,
password: process.env.MARIADB_Password,
databaseType: 'mariadb',
resultsPath: resultsPath,
convertCase: true
});
return engine;
}
function compileTsFiles(fileNames: string[], options: ts.CompilerOptions): boolean {
let program = ts.createProgram(fileNames, options);
let emitResult = program.emit();
let compileErrors = false;
let allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
allDiagnostics.forEach(diagnostic => {
let lineAndCharacter = diagnostic.file!.getLineAndCharacterOfPosition(diagnostic.start!);
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
console.log(`${diagnostic.file!.fileName} (${lineAndCharacter.line + 1},${lineAndCharacter.character + 1}): ${message}`);
compileErrors = true;
});
return compileErrors;
}

View File

@ -271,6 +271,20 @@ export class EntityFileToJson {
console.log(`[EntityFileToJson:convert] Line not recognized in entity ${retVal.entityName}:`)
console.log(`${trimmedLine}`)
}
retVal.columns=retVal.columns.map(col=>{
if (col.columnName.endsWith('Id'))
col.columnName=col.columnName.substr(0,col.columnName.length-2)
return col;
})
retVal.indicies=retVal.indicies.map(ind=>{
ind.columnNames=ind.columnNames.map(colName=>{
if (colName.endsWith('Id'))
colName=colName.substr(0,colName.length-2)
return colName;
})
return ind;
})
return retVal;
}
isPartOfMultilineStatement(statement: string) {

View File

@ -0,0 +1,206 @@
import * as ts from "typescript";
import { AbstractDriver } from "../../src/drivers/AbstractDriver";
import { MssqlDriver } from "../../src/drivers/MssqlDriver";
import { PostgresDriver } from "./../../src/drivers/PostgresDriver";
import { MysqlDriver } from "../../src/drivers/MysqlDriver";
import { MariaDbDriver } from "../../src/drivers/MariaDbDriver";
import { Engine } from "../../src/Engine";
import { createConnection, ConnectionOptions, Connection } from "typeorm";
import * as yn from "yn"
import path = require('path')
export async function createMSSQLModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new MssqlDriver();
await driver.ConnectToServer(`master`, String(process.env.MSSQL_Host), Number(process.env.MSSQL_Port), String(process.env.MSSQL_Username), String(process.env.MSSQL_Password), yn(process.env.MSSQL_SSL));
if (! await driver.CheckIfDBExists(String(process.env.MSSQL_Database)))
await driver.CreateDB(String(process.env.MSSQL_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
database: String(process.env.MSSQL_Database),
host: String(process.env.MSSQL_Host),
password: String(process.env.MSSQL_Password),
type: 'mssql',
username: String(process.env.MSSQL_Username),
port: Number(process.env.MSSQL_Port),
dropSchema: true,
synchronize: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new MssqlDriver();
let engine = new Engine(
driver, {
host: String(process.env.MSSQL_Host),
port: Number(process.env.MSSQL_Port),
databaseName: String(process.env.MSSQL_Database),
user: String(process.env.MSSQL_Username),
password: String(process.env.MSSQL_Password),
databaseType: 'mssql',
resultsPath: resultsPath,
schemaName: 'dbo',
ssl: yn(process.env.MSSQL_SSL)
});
return engine;
}
export async function createPostgresModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new PostgresDriver();
await driver.ConnectToServer(`postgres`, String(process.env.POSTGRES_Host), Number(process.env.POSTGRES_Port), String(process.env.POSTGRES_Username), String(process.env.POSTGRES_Password), yn(process.env.POSTGRES_SSL));
if (! await driver.CheckIfDBExists(String(process.env.POSTGRES_Database)))
await driver.CreateDB(String(process.env.POSTGRES_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
database: String(process.env.POSTGRES_Database),
host: String(process.env.POSTGRES_Host),
password: String(process.env.POSTGRES_Password),
type: 'postgres',
username: String(process.env.POSTGRES_Username),
port: Number(process.env.POSTGRES_Port),
dropSchema: true,
synchronize: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new PostgresDriver();
let engine = new Engine(
driver, {
host: String(process.env.POSTGRES_Host),
port: Number(process.env.POSTGRES_Port),
databaseName: String(process.env.POSTGRES_Database),
user: String(process.env.POSTGRES_Username),
password: String(process.env.POSTGRES_Password),
databaseType: 'postgres',
resultsPath: resultsPath,
schemaName: 'public',
ssl: yn(process.env.POSTGRES_SSL)
});
return engine;
}
export async function createMysqlModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new MysqlDriver();
await driver.ConnectToServer(`mysql`, String(process.env.MYSQL_Host), Number(process.env.MYSQL_Port), String(process.env.MYSQL_Username), String(process.env.MYSQL_Password), yn(process.env.MYSQL_SSL));
if (! await driver.CheckIfDBExists(String(process.env.MYSQL_Database)))
await driver.CreateDB(String(process.env.MYSQL_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
database: String(process.env.MYSQL_Database),
host: String(process.env.MYSQL_Host),
password: String(process.env.MYSQL_Password),
type: 'mysql',
username: String(process.env.MYSQL_Username),
port: Number(process.env.MYSQL_Port),
dropSchema: true,
synchronize: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new MysqlDriver();
let engine = new Engine(
driver, {
host: String(process.env.MYSQL_Host),
port: Number(process.env.MYSQL_Port),
databaseName: String(process.env.MYSQL_Database),
user: String(process.env.MYSQL_Username),
password: String(process.env.MYSQL_Password),
databaseType: 'mysql',
resultsPath: resultsPath,
schemaName: 'ignored',
ssl: yn(process.env.MYSQL_SSL)
});
return engine;
}
export async function createMariaDBModels(filesOrgPath: string, resultsPath: string): Promise<Engine> {
let driver: AbstractDriver;
driver = new MariaDbDriver();
await driver.ConnectToServer(`mysql`, String(process.env.MARIADB_Host), Number(process.env.MARIADB_Port), String(process.env.MARIADB_Username), String(process.env.MARIADB_Password), yn(process.env.MARIADB_SSL));
if (! await driver.CheckIfDBExists(String(process.env.MARIADB_Database)))
await driver.CreateDB(String(process.env.MARIADB_Database));
await driver.DisconnectFromServer();
let connOpt: ConnectionOptions = {
database: String(process.env.MARIADB_Database),
host: String(process.env.MARIADB_Host),
password: String(process.env.MARIADB_Password),
type: 'mariadb',
username: String(process.env.MARIADB_Username),
port: Number(process.env.MARIADB_Port),
dropSchema: true,
synchronize: true,
entities: [path.resolve(filesOrgPath, '*.js')],
}
let conn = await createConnection(connOpt)
if (conn.isConnected)
await conn.close()
driver = new MariaDbDriver();
let engine = new Engine(
driver, {
host: String(process.env.MARIADB_Host),
port: Number(process.env.MARIADB_Port),
databaseName: String(process.env.MARIADB_Database),
user: String(process.env.MARIADB_Username),
password: String(process.env.MARIADB_Password),
databaseType: 'mariadb',
resultsPath: resultsPath,
schemaName: 'ignored',
ssl: yn(process.env.MARIADB_SSL)
});
return engine;
}
export function compileTsFiles(fileNames: string[], options: ts.CompilerOptions): boolean {
let program = ts.createProgram(fileNames, options);
let emitResult = program.emit();
let compileErrors = false;
let preDiagnostics = ts.getPreEmitDiagnostics(program);
let allDiagnostics = [...preDiagnostics, ...emitResult.diagnostics];
allDiagnostics.forEach(diagnostic => {
let lineAndCharacter = diagnostic.file!.getLineAndCharacterOfPosition(diagnostic.start!);
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
console.log(`${diagnostic.file!.fileName} (${lineAndCharacter.line + 1},${lineAndCharacter.character + 1}): ${message}`);
compileErrors = true;
});
return compileErrors;
}

View File

@ -12,7 +12,8 @@
"stripInternal": true,
"strictNullChecks": true,
"moduleResolution": "node",
"outDir": "dist"
"outDir": "dist",
"newLine": "LF"
}, "include": [
"src",
"test"

View File

@ -4,6 +4,7 @@
},
"dependencies": {
"mssql": "registry:dt/mssql#3.3.0+20170311011547",
"yargs": "registry:npm/yargs#5.0.0+20160907000723"
"yargs": "registry:npm/yargs#5.0.0+20160907000723",
"yn": "registry:npm/yn#1.3.0+20170508185912"
}
}