├── .gitignore ├── LICENSE ├── README.md ├── doc ├── images │ ├── column-optional.png │ ├── column-primary.png │ ├── column-type.png │ ├── crm-svc.png │ ├── crud-svc-ctrls.png │ ├── empty-project.png │ ├── entity-class.png │ ├── entity-fieldset.png │ ├── entity-fieldset2.png │ ├── entity-folder.png │ ├── entity-stereotype.png │ ├── module-selection.png │ ├── module-stereotype.png │ ├── module-stereotype2.png │ ├── module-stereotype3.png │ ├── node_modules.png │ ├── relation-navi.png │ └── relation-tree.png └── sample │ └── Salesforce.mdj ├── lib ├── code-generator.js ├── code-helper.js ├── code-writer.js ├── crud-generator.js └── meta-generator.js ├── main.js ├── menus └── menu.json ├── node_modules ├── lodash.camelcase │ ├── LICENSE │ ├── README.md │ ├── index.js │ └── package.json ├── lodash.capitalize │ ├── LICENSE │ ├── README.md │ ├── index.js │ └── package.json ├── lodash.kebabcase │ ├── LICENSE │ ├── README.md │ ├── index.js │ └── package.json ├── lodash.snakecase │ ├── LICENSE │ ├── README.md │ ├── index.js │ └── package.json └── pluralize │ ├── LICENSE │ ├── Readme.md │ ├── package.json │ └── pluralize.js ├── package-lock.json ├── package.json └── preferences └── preference.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Jianfeng Jin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StarUML NestJS CRUD Generator 2 | The generator is target to generate controllers and services for [nestjsx/crud](https://github.com/nestjsx/crud) and [nestjs/swagger](https://github.com/nestjs/swagger) based on [typeorm](https://github.com/typeorm/typeorm) entities. You will only need to draw typeorm entities and their relationships, the rest will be handled by the tool automatically. Features: 3 | 4 | - Support embedded entities (classes with stereotype `fields`). 5 | - Support all kinds of entity relationships (even trees). 6 | - Support cross module references. 7 | - Generate ready to use CRUD APIs and Swagger Docs. 8 | 9 | The followings are entities borrowed from Salesforce CRM platform. As you can see, there are many-to-many, many-to-one and one-to-many relationships etc. The `AddressFields`, `SystemFields` classes are embedded entities with stereotype `fields`. We will dive into details later on. 10 | 11 | ![](./doc/images/crm-svc.png) 12 | 13 | 14 | 15 | ## Overview 16 | 17 | In order to support the above features, there are a few rules need to be followed. Some are self invented terms such as `fields` stereotype for embedded entities. Although it sounds complex, it is easy to use with the following main steps in mind: 18 | 19 | 1. Create an empty StarUML project 20 | 2. Add node_modules package automatically 21 | 3. Draw entity relationship class diagram manually 22 | 4. Add crud services and controllers automatically 23 | 5. Generate nestjs code automatically 24 | 25 | As you can see only the 3rd step requires manual configuration. The library currently only runs positive test cases, and complex class/interface inheritances have not been tested. However for just entity relationship diagrams, the current implementaion is sufficient. 26 | 27 | ## Installation 28 | 29 | If the "Install From URL.." option does not work for you, by putting the github project url into the text field. Please directly download the soruce code and put the `staruml-nestjs` folder under the following directory accordingly. 30 | 31 | - MAC OS: `/Users//Library/Application Support/StarUML/extensions/user` 32 | - Windows: `C:\Users\\AppData\Roaming\StarUML\extensions\user` 33 | - Linux: `~/.config/StarUML/extensions/user` 34 | 35 | ## Quick Start 36 | 37 | For a quick start, please just download the sample [Salesforce.mdj](./doc/sample/Salesforce.mdj) file directly. To generate your first NestJS module, please follow these steps: 38 | 39 | 1. Double click to open Salesforce.mdj. 40 | 2. Click Menu Item: **Tools** => **NestJS** => **Generate Code...** 41 | 3. Select any module (the package with `<>` stereotype), such as app or sales. 42 | 4. Press OK and select a directory to output the generated source codes. 43 | 44 | ## 1. Create a StarUML Project 45 | 46 | 1. Create an empty StarUML project. 47 | - The red cube represents a StarUML project, similarly to NodeJS/NestJS project root folder where package.json file resides. 48 | - The Model (folder icon with a triangle in it) is equivalent to an `src` folder in NodeJS/NestJS world. 49 | - The green icon named `Main` is the class diagram. 50 | 51 | ## 2. Add node_modules Meta Classes 52 | 53 | 1. Click menu item: **Tools** => **NestJS** => **Add Meta Class...** 54 | 2. Select the red cube StarUML project, and press OK. 55 | 3. The `node_modules` package will be generated under the project. These are mainly used as stereotypes during entity and relationship creation. 56 | 57 | 58 | ## 3. Draw Class Diagram 59 | 60 | ### 3.1 Create Module/Folder 61 | 62 | Module is just a StarUML package with stereotype `Module`. StarUML package is the fundamental element to organize classes. Each package with/without stereotype will be treated as a folder. And the package name will be directed used as the folder name. So we don't follow `com.nestjs.package` java naming convention for the package names. During the generation, a `name-of-something.module.ts` file with proper import and declaration will be created for you. Please follow the following steps to create a module: 63 | 64 | 1. Right click on Model. 65 | 2. Click Add => Package. 66 | 3. Rename Package to `app` or any appropriate module name. 67 | 4. Assign `<>` stereotype by clicking the magnifying glass icon besides the stereotype field. 68 | 5. Type `Module` to search for the class `Module` under `nestjs/common` package. Select it and press OK button. 69 | 6. And make sure there is a yellow class icon besides the stereotype selected. If you type the `Module` string directly into the stereotype text field, the class icon won't appear. 70 | 71 | ### 3.2 Create Entities 72 | 73 | Entities are just plain UML classes with stereotype `Entity`. The generated entity file name will look like `name-of-something.entity.ts`. **Note**: there will be corresponding model classes generated for every entity classes implicitly. The model class name will be the entity class name suffixed with `Model`. The generated model file name will look like `name-of-something.model.ts`. 74 | 75 | 1. In order to add new Entity classes later, let's create a new package `entities` under the module we created above. This is for better organize the generated entity class files. 76 | 2. Right click the `entities` package created above. 77 | 3. Click Add => Class. 78 | 4. Use `Entity` class as its stereotype. Please use the magnifying glass to search the class as we did for modules. And make sure the yellow class icon is present besides the stereotype selected. 79 | 5. Drag and drop the newly created class onto the diagram, so we can visually add columns later. 80 | 81 | ### 3.3 Create Embed Entities (FieldSet) 82 | 83 | embedded entities are just plain UML classes with stereotype `FieldSet`. The class name should be suffixed with `FieldSet` as well. The generated class names will look like `name-of-something.fieldset.ts`. 84 | 85 | 1. Right click the `entities` package created above. 86 | 2. Click Add => Class, and rename it with `FieldSet` suffix. 87 | 3. Just type `FieldSet` in the stereotype text field. **Caution**: there is no corresponding meta class for FieldSet. 88 | 4. Drag and drop the newly created class onto the diagram, so we can visually add columns later. 89 | 90 | ### 3.4 Create Columns 91 | 92 | #### Data Types 93 | 94 | All valid typeorm data types or FieldSet class types can be used as column data types, such as `string`, `number`, `boolean`, or `Date` etc. When referencing `FieldSet` as data types, the correct class type can be automatically resolved after typing. As you can see the yellow class icon is present besides the type property. Please double check this if any data type reference is not imported for the entity after code generation. The `FieldSet` class can resides in `<>` package other than the current entity module, such as a shared module. 95 | 96 | 97 | #### Optional Columns 98 | 99 | Please add the `?` mark after the name for optional columns. In the following example, industry is an optional column. 100 | 101 | 102 | #### Primary Columns 103 | 104 | Check the `isID` checkbox for typeorm `PrimanyColumn`. And also check the `isDerived` checkbox if it is a typeorm `PrimanyGeneratedColumn`. 105 | 106 | 107 | ### 3.5 Establish Relationships 108 | 109 | **Note**: All relationships are UML associations, and must be drawn in the direction from Child to Parent. 110 | 111 | #### One-to-One 112 | 113 | ``` 114 | |---------| |---------| 115 | | Parent | | Child | 116 | |---------|-----------------|---------| 117 | |---------| |---------| 118 | ``` 119 | 120 | 1. Just draw a plain association from child to parent class. 121 | 122 | #### One-to-Many/Many-to-One 123 | 124 | ``` 125 | |---------| |---------| 126 | | Parent | 0..*| Child | 127 | |---------|-----------------|---------| 128 | |---------| |---------| 129 | ``` 130 | 131 | 1. Just draw a plain association from child to parent class. 132 | 2. And change the multiplicity at child end to a range above 1. For simplicity, let's just use `0..*`. 133 | 134 | #### Many-to-Many 135 | ``` 136 | |---------| |---------| 137 | | Parent |0..* 0..*| Child | 138 | |---------|-----------------|---------| 139 | |---------| |---------| 140 | ``` 141 | 142 | 1. Just draw a plain association from child to parent class. 143 | 2. Change the multiplicity at both child and parent end to a range above 1. For simplicity, let's just use `0..*`. 144 | 145 | #### Unidirectional Reference 146 | 147 | ``` 148 | |---------| |---------| 149 | | Parent | 0..*| Child | 150 | |---------|<----------------|---------| 151 | |---------| |---------| 152 | ``` 153 | 154 | If you don't want the Parent class have an array field referencing its children, but Child class have a field referencing its parent instance, or vice versa. Please disable the navigable at the Child end. Since we always draw from Child to Parent, it is the end1.navigable checkbox that needs to be unchecked. By doing this, the association at parent end will turn into an arrow. 155 | 156 | 157 | #### Self Reference 158 | 159 | Self referencing is allowed, and must be one-to-many/many-to-one relationship. If typeorm tree structure is needed for the self referencing hierarchy relationship. Please assign the stereotype of the association to the `Tree` class under `typeorm` package. 160 | 161 | 162 | By default `materialized-path` strategy will be used to establish the tree structure. If other strategies are used, please specify it as the association name. For a complete tree establish strategy, please refer to typeorm [Tree Entities](https://typeorm.io/#/tree-entities) document. 163 | 164 | ## 4. Add CRUD Service and Controller Classes 165 | 166 | 1. Click menu item: **Tools** => **NestJS** => **Add Crud Class...** 167 | 2. Select top or sub `<>` package containing entities. 168 | 3. Press OK, the services and controllers will be generated under their corresponding folders. 169 | 4. The services and controllers package in above screenshot are automatically created to organize the newly added classes. However, entities are not required to be under the entities folder, they can be anywhere within the `` package. 170 | 171 | ## 5. Generate NestJS Code 172 | 173 | 1. Click Menu Item: **Tools** => **NestJS** => **Generate Code...** 174 | 2. Select any module (the package with `<>` stereotype). 175 | 3. Press OK and select a directory to output the generated soruce codes. 176 | 177 | ## Finally 178 | 179 | In order to run the generated code, we have to put them into a NestJS project with additional npm packages installed. Please refer to official docs on how to [nestjsx/crud](https://github.com/nestjsx/crud) and [nestjs/swagger](https://github.com/nestjs/swagger). 180 | 181 | ```yaml 182 | "@nestjs/swagger": "^3.1.0", 183 | "@nestjsx/crud": "^4.2.0", 184 | "@nestjsx/crud-typeorm": "^4.2.0", 185 | "class-transformer": "^0.2.3", 186 | "class-validator": "^0.10.2", 187 | "swagger-ui-express": "^4.1.2", 188 | ``` 189 | 190 | Please don't forget to import the generated modules. And the `main.ts` should look like the followings: 191 | 192 | ```typescript 193 | import { CrudConfigService } from '@nestjsx/crud'; 194 | import { NestFactory } from '@nestjs/core'; 195 | import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; 196 | import { AppModule } from './app.module'; 197 | 198 | async function bootstrap() { 199 | const app = await NestFactory.create( 200 | AppModule.forRoot(), 201 | ); 202 | 203 | const options = new DocumentBuilder() 204 | .setTitle('API Document') 205 | .setVersion('1.0') 206 | .build(); 207 | const document = SwaggerModule.createDocument(app, options); 208 | SwaggerModule.setup('docs', app, document); 209 | 210 | await app.listen(process.env.PORT || 3000); 211 | } 212 | bootstrap(); 213 | ``` 214 | 215 | ## License 216 | MIT 217 | -------------------------------------------------------------------------------- /doc/images/column-optional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/column-optional.png -------------------------------------------------------------------------------- /doc/images/column-primary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/column-primary.png -------------------------------------------------------------------------------- /doc/images/column-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/column-type.png -------------------------------------------------------------------------------- /doc/images/crm-svc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/crm-svc.png -------------------------------------------------------------------------------- /doc/images/crud-svc-ctrls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/crud-svc-ctrls.png -------------------------------------------------------------------------------- /doc/images/empty-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/empty-project.png -------------------------------------------------------------------------------- /doc/images/entity-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/entity-class.png -------------------------------------------------------------------------------- /doc/images/entity-fieldset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/entity-fieldset.png -------------------------------------------------------------------------------- /doc/images/entity-fieldset2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/entity-fieldset2.png -------------------------------------------------------------------------------- /doc/images/entity-folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/entity-folder.png -------------------------------------------------------------------------------- /doc/images/entity-stereotype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/entity-stereotype.png -------------------------------------------------------------------------------- /doc/images/module-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/module-selection.png -------------------------------------------------------------------------------- /doc/images/module-stereotype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/module-stereotype.png -------------------------------------------------------------------------------- /doc/images/module-stereotype2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/module-stereotype2.png -------------------------------------------------------------------------------- /doc/images/module-stereotype3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/module-stereotype3.png -------------------------------------------------------------------------------- /doc/images/node_modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/node_modules.png -------------------------------------------------------------------------------- /doc/images/relation-navi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/relation-navi.png -------------------------------------------------------------------------------- /doc/images/relation-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nestfarm/staruml-nestjs/4b02e299133a37f5bf72a72c0a70f9de17a54458/doc/images/relation-tree.png -------------------------------------------------------------------------------- /lib/code-generator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 MKLab. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | const fs = require('fs') 25 | const path = require('path') 26 | const { CodeWriter } = require('./code-writer') 27 | const { CodeHelper } = require('./code-helper') 28 | const kebabCase = require('lodash.kebabcase') 29 | const camelCase = require('lodash.camelcase') 30 | const snakeCase = require('lodash.snakecase') 31 | const pluralize = require('pluralize') 32 | const capitalize = require('lodash.capitalize') 33 | const codeHelper = new CodeHelper() 34 | const keywords = { 35 | break: true, 36 | case: true, 37 | catch: true, 38 | continue: true, 39 | debugger: true, 40 | default: true, 41 | delete: true, 42 | do: true, 43 | else: true, 44 | finally: true, 45 | for: true, 46 | function: true, 47 | if: true, 48 | in: true, 49 | instanceof: true, 50 | new: true, 51 | return: true, 52 | switch: true, 53 | this: true, 54 | throw: true, 55 | try: true, 56 | typeof: true, 57 | var: true, 58 | void: true, 59 | while: true, 60 | with: true, 61 | } 62 | 63 | /** 64 | * Java Code Generator 65 | */ 66 | class NestCodeGenerator { 67 | 68 | /** 69 | * @constructor 70 | * 71 | * @param {type.UMLPackage} baseModel 72 | * @param {string} basePath generated files and directories to be placed 73 | */ 74 | constructor(baseModel, basePath) { 75 | /** @member {type.Model} */ 76 | this.baseModel = baseModel 77 | 78 | /** @member {string} */ 79 | this.basePath = basePath 80 | this.entities = [] 81 | this.services = [] 82 | this.controllers = [] 83 | } 84 | 85 | /** 86 | * Return Indent String based on options 87 | * @param {Object} options 88 | * @return {string} 89 | */ 90 | getIndentString(options) { 91 | if (options.useTab) { 92 | return '\t' 93 | } else { 94 | var i 95 | var len 96 | var indent = [] 97 | for (i = 0, len = options.indentSpaces; i < len; i++) { 98 | indent.push(' ') 99 | } 100 | return indent.join('') 101 | } 102 | } 103 | 104 | /** 105 | * Generate codes from a given element 106 | * @param {type.Model} elem 107 | * @param {string} basePath 108 | * @param {Object} options 109 | */ 110 | generate(elem, basePath, options) { 111 | var fullPath 112 | var codeWriter 113 | 114 | // Package 115 | if (elem instanceof type.UMLPackage) { 116 | fullPath = path.join(basePath, elem.name) 117 | fs.mkdirSync(fullPath) 118 | if (Array.isArray(elem.ownedElements)) { 119 | elem.ownedElements.forEach(child => { 120 | return this.generate(child, fullPath, options) 121 | }) 122 | } 123 | if (elem.stereotype instanceof type.UMLClass && elem.stereotype.name === 'Module') { 124 | codeWriter = new CodeWriter(this.getIndentString(options)) 125 | this.writeModule(codeWriter, elem, options) 126 | let modPath = fullPath + '/' + codeHelper.getFileName(elem) + '.ts' 127 | fs.writeFileSync(modPath, codeWriter.getData()) 128 | this.entities = [] 129 | this.services = [] 130 | this.controllers = [] 131 | } 132 | } else if (elem instanceof type.UMLClass) { 133 | // Decorator 134 | if (elem.stereotype === 'annotationType') { 135 | fullPath = path.join(basePath, elem.name + '.java') 136 | codeWriter = new CodeWriter(this.getIndentString(options)) 137 | codeWriter.writeLine() 138 | codeWriter.writeLine('import java.util.*;') 139 | codeWriter.writeLine() 140 | this.writeAnnotationType(codeWriter, elem, options) 141 | fs.writeFileSync(fullPath, codeWriter.getData()) 142 | // Entity 143 | } else if ((elem.stereotype instanceof type.UMLClass 144 | && elem.stereotype.name === 'Entity') 145 | || elem.stereotype === 'FieldSet') { 146 | 147 | if (elem.stereotype.name === 'Entity') { 148 | this.entities.push(elem) 149 | } 150 | fullPath = basePath + '/' + codeHelper.getFileName(elem) + '.ts' 151 | codeWriter = new CodeWriter(this.getIndentString(options)) 152 | this.writeEntity(codeWriter, elem, options) 153 | fs.writeFileSync(fullPath, codeWriter.getData()) 154 | 155 | // Model 156 | basePath = path.join(basePath, '../models') 157 | if (!fs.existsSync(basePath)) { 158 | fs.mkdirSync(basePath) 159 | } 160 | elem.isModel = true; // begin use entity as model 161 | fullPath = path.join(basePath, codeHelper.getFileName(elem) + '.ts') 162 | codeWriter = new CodeWriter(this.getIndentString(options)) 163 | this.writeModel(codeWriter, elem, options) 164 | fs.writeFileSync(fullPath, codeWriter.getData()) 165 | delete elem.isModel // finish use entity as model 166 | // Class 167 | } else if (elem.stereotype instanceof type.UMLClass 168 | && elem.stereotype.name === 'Injectable') { 169 | this.services.push(elem) 170 | 171 | fullPath = basePath + '/' + codeHelper.getFileName(elem) + '.ts' 172 | codeWriter = new CodeWriter(this.getIndentString(options)) 173 | this.writeCrudService(codeWriter, elem, options) 174 | fs.writeFileSync(fullPath, codeWriter.getData()) 175 | } else if (elem.stereotype instanceof type.UMLClass 176 | && elem.stereotype.name === 'Controller') { 177 | this.controllers.push(elem) 178 | 179 | fullPath = basePath + '/' + codeHelper.getFileName(elem) + '.ts' 180 | codeWriter = new CodeWriter(this.getIndentString(options)) 181 | this.writeCrudController(codeWriter, elem, options) 182 | fs.writeFileSync(fullPath, codeWriter.getData()) 183 | } 184 | // Interface 185 | } else if (elem instanceof type.UMLInterface) { 186 | fullPath = basePath + '/' + elem.name + '.java' 187 | codeWriter = new CodeWriter(this.getIndentString(options)) 188 | codeWriter.writeLine() 189 | codeWriter.writeLine('import java.util.*;') 190 | codeWriter.writeLine() 191 | this.writeInterface(codeWriter, elem, options) 192 | fs.writeFileSync(fullPath, codeWriter.getData()) 193 | 194 | // Enum 195 | } else if (elem instanceof type.UMLEnumeration) { 196 | fullPath = basePath + '/' + elem.name + '.java' 197 | codeWriter = new CodeWriter(this.getIndentString(options)) 198 | codeWriter.writeLine() 199 | this.writeEnum(codeWriter, elem, options) 200 | fs.writeFileSync(fullPath, codeWriter.getData()) 201 | } 202 | } 203 | 204 | /** 205 | * Return visibility 206 | * @param {type.Model} elem 207 | * @return {string} 208 | */ 209 | getVisibility(elem) { 210 | switch (elem.visibility) { 211 | case type.UMLModelElement.VK_PUBLIC: 212 | return 'public' 213 | case type.UMLModelElement.VK_PROTECTED: 214 | return 'protected' 215 | case type.UMLModelElement.VK_PRIVATE: 216 | return 'private' 217 | } 218 | return null 219 | } 220 | 221 | /** 222 | * Collect modifiers of a given element. 223 | * @param {type.Model} elem 224 | * @return {Array.} 225 | */ 226 | getModifiers(elem, withVisibility = true) { 227 | var modifiers = [] 228 | 229 | if (withVisibility) { 230 | var visibility = this.getVisibility(elem) 231 | if (visibility) { 232 | modifiers.push(visibility) 233 | } 234 | } 235 | 236 | if (elem.isStatic === true) { 237 | modifiers.push('static') 238 | } 239 | if (elem.isAbstract === true) { 240 | modifiers.push('abstract') 241 | } 242 | if (elem.isFinalSpecialization === true || elem.isLeaf === true) { 243 | modifiers.push('final') 244 | } 245 | if (elem.concurrency === type.UMLBehavioralFeature.CCK_CONCURRENT) { 246 | modifiers.push('synchronized') 247 | } 248 | // transient 249 | // strictfp 250 | // const 251 | // native 252 | return modifiers 253 | } 254 | 255 | /** 256 | * Collect super classes of a given element 257 | * @param {type.Model} elem 258 | * @return {Array.} 259 | */ 260 | getSuperClasses(elem) { 261 | var generalizations = app.repository.getRelationshipsOf(elem, function (rel) { 262 | return (rel instanceof type.UMLGeneralization && rel.source === elem) 263 | }) 264 | return generalizations.map(function (gen) { return gen.target }) 265 | } 266 | 267 | /** 268 | * Collect super interfaces of a given element 269 | * @param {type.Model} elem 270 | * @return {Array.} 271 | */ 272 | getSuperInterfaces(elem) { 273 | var realizations = app.repository.getRelationshipsOf(elem, function (rel) { 274 | return (rel instanceof type.UMLInterfaceRealization && rel.source === elem) 275 | }) 276 | return realizations.map(function (gen) { return gen.target }) 277 | } 278 | 279 | getName(elem) { 280 | var _name = '' 281 | // type name 282 | if (elem instanceof type.UMLAssociationEnd) { 283 | if (elem.name.length > 0) { 284 | _name = elem.name 285 | } else if (elem.reference instanceof type.UMLModelElement 286 | && elem.reference.name.length > 0) { 287 | _name = elem.reference.name 288 | } 289 | } else { 290 | _name = elem.name 291 | } 292 | 293 | let isOptional = _name.endsWith('?') 294 | if (this.hasMultiple(elem)) { 295 | return camelCase(pluralize(_name)) + (isOptional ? '?' : '') 296 | } else { 297 | return camelCase(_name) + (isOptional ? '?' : '') 298 | } 299 | } 300 | 301 | /** 302 | * Return type expression 303 | * @param {type.Model} elem 304 | * @return {string} 305 | */ 306 | getType(elem) { 307 | var _type = 'void' 308 | // type name 309 | if (elem instanceof type.UMLAssociationEnd) { 310 | if (elem.reference instanceof type.UMLModelElement && elem.reference.name.length > 0) { 311 | _type = elem.reference.name + (elem.reference.isModel ? 'Model' : '') 312 | } 313 | } else { 314 | if (elem.type instanceof type.UMLModelElement && elem.type.name.length > 0) { 315 | _type = elem.type.name + (elem.type.isModel ? 'Model' : '') 316 | } else if ((typeof elem.type === 'string') && elem.type.length > 0) { 317 | _type = elem.type 318 | } 319 | } 320 | 321 | if (this.hasMultiple(elem)) { 322 | _type += '[]' 323 | } 324 | return _type 325 | } 326 | 327 | hasMultiple(elem) { 328 | if (elem.multiplicity) { 329 | if (['0..*', '1..*', '*'].includes(elem.multiplicity.trim())) { 330 | return true; 331 | } else if (elem.multiplicity !== '1' && elem.multiplicity.match(/^\d+$/)) { // number 332 | return true; 333 | } 334 | } 335 | } 336 | 337 | getEntityColumnOptions(elem) { 338 | let options = [] 339 | if (elem.name.endsWith('?')) { 340 | options.push({ 341 | key: "nullable", 342 | val: true 343 | }) 344 | } 345 | 346 | if (elem.defaultValue && elem.defaultValue.length > 0) { 347 | let defaultValue = elem.defaultValue 348 | if (elem.defaultValue.toLowerCase() === 'true' || elem.defaultValue.toUpperCase() === 'false') { 349 | defaultValue = elem.defaultValue.toLowerCase() === 'true'; 350 | } else if (!Number.isNaN(Number(elem.defaultValue))) { 351 | defaultValue = Number(elem.defaultValue); 352 | } 353 | options.push({ 354 | key: "default", 355 | val: defaultValue 356 | }) 357 | } 358 | return options; 359 | } 360 | 361 | /** 362 | * Write Doc 363 | * @param {StringWriter} codeWriter 364 | * @param {string} text 365 | * @param {Object} options 366 | */ 367 | writeDoc(codeWriter, text, options) { 368 | var i, len, lines 369 | if (options.javaDoc && (typeof text === 'string')) { 370 | lines = text.trim().split('\n') 371 | codeWriter.writeLine('/**') 372 | for (i = 0, len = lines.length; i < len; i++) { 373 | codeWriter.writeLine(' * ' + lines[i]) 374 | } 375 | codeWriter.writeLine(' */') 376 | } 377 | } 378 | 379 | /** 380 | * Write Package Declaration 381 | * @param {StringWriter} codeWriter 382 | * @param {type.Model} elem 383 | * @param {Object} options 384 | */ 385 | writePackageDeclaration(codeWriter, elem, options) { 386 | var packagePath = null 387 | if (elem._parent) { 388 | packagePath = elem._parent.getPath(this.baseModel).map(function (e) { return e.name }).join('.') 389 | } 390 | if (packagePath) { 391 | codeWriter.writeLine('package ' + packagePath + ';') 392 | } 393 | } 394 | 395 | /** 396 | * Write Constructor 397 | * @param {StringWriter} codeWriter 398 | * @param {type.Model} elem 399 | * @param {Object} options 400 | */ 401 | writeConstructor(codeWriter, elem, options) { 402 | if (elem.name.length > 0) { 403 | var terms = [] 404 | // Doc 405 | this.writeDoc(codeWriter, 'Default constructor', options) 406 | // Visibility 407 | var visibility = this.getVisibility(elem) 408 | if (visibility) { 409 | terms.push(visibility) 410 | } 411 | terms.push(elem.name + '()') 412 | codeWriter.writeLine(terms.join(' ') + ' {') 413 | codeWriter.writeLine('}') 414 | } 415 | } 416 | 417 | useTree(asso) { 418 | return asso instanceof type.UMLAssociation 419 | && asso.end1.reference === asso.end2.reference 420 | && asso.stereotype instanceof type.UMLClass 421 | && asso.stereotype.name === 'Tree' 422 | } 423 | 424 | /** 425 | * Write Member Variable 426 | * @param {StringWriter} codeWriter 427 | * @param {type.Model} elem 428 | * @param {Object} options 429 | */ 430 | writeMemberVariable(codeWriter, elem, options) { 431 | var name = this.getName(elem) 432 | var useTree = this.useTree(elem._parent) 433 | if (useTree && !elem.name) { 434 | if (this.hasMultiple(elem)) { 435 | name = 'children' 436 | } else { 437 | name = 'parent' 438 | } 439 | } 440 | if (name.length > 0) { 441 | var terms = [] 442 | // doc 443 | // this.writeDoc(codeWriter, elem.documentation, options) 444 | // modifiers 445 | var _modifiers = this.getModifiers(elem) 446 | if (_modifiers.length > 0) { 447 | terms.push(_modifiers.join(' ')) 448 | } 449 | // name 450 | terms.push(name + ':') 451 | // type 452 | terms.push(this.getType(elem)) 453 | // initial value 454 | if (elem.defaultValue && elem.defaultValue.length > 0) { 455 | terms.push('= ' + elem.defaultValue) 456 | } 457 | codeWriter.writeLine(terms.join(' ') + ';') 458 | } 459 | } 460 | 461 | /** 462 | * Write Member Variable 463 | * @param {StringWriter} codeWriter 464 | * @param {type.Model} elem 465 | * @param {Object} options 466 | */ 467 | writeEntityColumn(codeWriter, elem, options) { 468 | var column 469 | var pkg = 'typeorm' 470 | 471 | if (elem.isID) { 472 | if (elem.isDerived) { 473 | column = 'PrimaryGeneratedColumn' 474 | } else { 475 | column = 'PrimaryColumn' 476 | } 477 | } else { 478 | if (elem.stereotype instanceof type.UMLClass && elem.stereotype.name.length > 0) { 479 | column = elem.stereotype.name 480 | pkg = codeHelper.getImportPath(elem, elem.stereotype) 481 | } else { 482 | column = 'Column' 483 | } 484 | } 485 | 486 | codeWriter.import(column, pkg) 487 | let colOptions = this.getEntityColumnOptions(elem) 488 | if (Object.keys(colOptions).length > 0) { 489 | codeWriter.writeLine(`@${column}({ ${colOptions.map(o => o.key + ': ' + o.val).join(', ')} })`) 490 | } else if (elem.type instanceof type.UMLModelElement && elem.type.name.length > 0) { 491 | codeWriter.import(elem.type.name, codeHelper.getImportPath(elem, elem.type)) 492 | codeWriter.writeLine(`@${column}(type => ${elem.type.name})`) 493 | } else { 494 | codeWriter.writeLine(`@${column}()`) 495 | } 496 | 497 | this.writeMemberVariable(codeWriter, elem, options) 498 | } 499 | 500 | writeModelRelation(codeWriter, { from, to }, options) { 501 | from.reference.isModel = true 502 | to.reference.isModel = true 503 | if (from.reference !== to.reference) { 504 | codeWriter.import(to.reference.name + 'Model', 505 | codeHelper.getImportPath(from.reference, to.reference)) 506 | } 507 | 508 | if (to.reference.name.endsWith('?')) { 509 | codeWriter.writeLine('@ApiModelPropertyOptional()') 510 | } else { 511 | codeWriter.writeLine('@ApiModelProperty()') 512 | } 513 | this.writeMemberVariable(codeWriter, to, options) 514 | codeWriter.writeLine() 515 | delete from.reference.isModel 516 | delete to.reference.isModel 517 | } 518 | 519 | /** 520 | * Write Member Variable 521 | * @param {StringWriter} codeWriter 522 | * @param {type.Model} elem 523 | * @param {Object} options 524 | */ 525 | writeEntityRelation(codeWriter, asso, options, { from, to, element: elem }) { 526 | var column 527 | var useTree = this.useTree(asso) 528 | 529 | if (to) { 530 | if (useTree) { 531 | if (this.hasMultiple(from)) { 532 | column = 'TreeParent' 533 | } else { 534 | column = 'TreeChildren' 535 | } 536 | } else { 537 | if (this.hasMultiple(from)) { 538 | if (this.hasMultiple(to)) { 539 | column = 'ManyToMany' 540 | } else { 541 | column = 'ManyToOne' 542 | } 543 | } else { 544 | if (this.hasMultiple(to)) { 545 | column = 'OneToMany' 546 | } else { 547 | column = 'OneToOne' 548 | } 549 | } 550 | } 551 | 552 | codeWriter.import(column, 'typeorm') 553 | if (useTree) { 554 | codeWriter.writeLine(`@${column}()`) 555 | } else { 556 | let fromEntity = this.getName(from) 557 | let toField = this.getName(to.reference) 558 | toField = keywords[toField] ? '_' + toField : toField 559 | 560 | if (from.navigable) { 561 | codeWriter.writeLine(`@${column}(type => ${to.reference.name}, ${toField} => ${toField}.${fromEntity})`) 562 | } else { 563 | codeWriter.writeLine(`@${column}(type => ${to.reference.name})`) 564 | } 565 | 566 | var joinColumn = (column === 'ManyToMany') 567 | ? ((asso.end1.reference === elem) ? 'JoinTable' : '') 568 | : ((asso.end1.reference === elem) ? 'JoinColumn' : '') 569 | if (joinColumn) { 570 | codeWriter.import(joinColumn, 'typeorm') 571 | codeWriter.writeLine(`@${joinColumn}()`) 572 | } 573 | if (from.reference !== to.reference) { 574 | codeWriter.import(to.reference.name, 575 | codeHelper.getImportPath(from.reference, to.reference)) 576 | } 577 | } 578 | 579 | this.writeMemberVariable(codeWriter, to, options) 580 | codeWriter.writeLine() 581 | } 582 | } 583 | 584 | /** 585 | * Write Method 586 | * @param {StringWriter} codeWriter 587 | * @param {type.Model} elem 588 | * @param {Object} options 589 | * @param {boolean} skipBody 590 | * @param {boolean} skipParams 591 | */ 592 | writeMethod(codeWriter, elem, options, skipBody, skipParams) { 593 | if (elem.name.length > 0) { 594 | var terms = [] 595 | var params = elem.getNonReturnParameters() 596 | var returnParam = elem.getReturnParameter() 597 | 598 | // doc 599 | var doc = elem.documentation.trim() 600 | 601 | // Erase Javadoc @param and @return 602 | var i 603 | var lines = doc.split('\n') 604 | doc = '' 605 | for (i = 0, len = lines.length; i < len; i++) { 606 | if (lines[i].lastIndexOf('@param', 0) !== 0 && lines[i].lastIndexOf('@return', 0) !== 0) { 607 | doc += '\n' + lines[i] 608 | } 609 | } 610 | 611 | params.forEach(function (param) { 612 | doc += '\n@param ' + param.name + ' ' + param.documentation 613 | }) 614 | if (returnParam) { 615 | doc += '\n@return ' + returnParam.documentation 616 | } 617 | this.writeDoc(codeWriter, doc, options) 618 | 619 | // modifiers 620 | var _modifiers = this.getModifiers(elem) 621 | if (_modifiers.length > 0) { 622 | terms.push(_modifiers.join(' ')) 623 | } 624 | 625 | // type 626 | if (returnParam) { 627 | terms.push(this.getType(returnParam)) 628 | } else { 629 | terms.push('void') 630 | } 631 | 632 | // name + parameters 633 | var paramTerms = [] 634 | if (!skipParams) { 635 | var len 636 | for (i = 0, len = params.length; i < len; i++) { 637 | var p = params[i] 638 | var s = this.getType(p) + ' ' + p.name 639 | if (p.isReadOnly === true) { 640 | s = 'final ' + s 641 | } 642 | paramTerms.push(s) 643 | } 644 | } 645 | terms.push(elem.name + '(' + paramTerms.join(', ') + ')') 646 | 647 | // body 648 | if (skipBody === true || _modifiers.includes('abstract')) { 649 | codeWriter.writeLine(terms.join(' ') + ';') 650 | } else { 651 | codeWriter.writeLine(terms.join(' ') + ' {') 652 | codeWriter.indent() 653 | codeWriter.writeLine('// TODO implement here') 654 | 655 | // return statement 656 | if (returnParam) { 657 | var returnType = this.getType(returnParam) 658 | if (returnType === 'boolean') { 659 | codeWriter.writeLine('return false;') 660 | } else if (returnType === 'int' || returnType === 'long' || returnType === 'short' || returnType === 'byte') { 661 | codeWriter.writeLine('return 0;') 662 | } else if (returnType === 'float') { 663 | codeWriter.writeLine('return 0.0f;') 664 | } else if (returnType === 'double') { 665 | codeWriter.writeLine('return 0.0d;') 666 | } else if (returnType === 'char') { 667 | codeWriter.writeLine('return "0";') 668 | } else if (returnType === 'String') { 669 | codeWriter.writeLine('return "";') 670 | } else { 671 | codeWriter.writeLine('return null;') 672 | } 673 | } 674 | 675 | codeWriter.outdent() 676 | codeWriter.writeLine('}') 677 | } 678 | } 679 | } 680 | 681 | /** 682 | * Write Class 683 | * @param {StringWriter} codeWriter 684 | * @param {type.Model} elem 685 | * @param {Object} options 686 | */ 687 | writeClass(codeWriter, elem, options) { 688 | var i, len 689 | var terms = [] 690 | 691 | // Doc 692 | var doc = elem.documentation.trim() 693 | if (app.project.getProject().author && app.project.getProject().author.length > 0) { 694 | doc += '\n@author ' + app.project.getProject().author 695 | } 696 | this.writeDoc(codeWriter, doc, options) 697 | 698 | // Modifiers 699 | var _modifiers = this.getModifiers(elem) 700 | if (_modifiers.includes('abstract') !== true && elem.operations.some(function (op) { return op.isAbstract === true })) { 701 | _modifiers.push('abstract') 702 | } 703 | if (_modifiers.length > 0) { 704 | terms.push(_modifiers.join(' ')) 705 | } 706 | 707 | // Class 708 | terms.push('class') 709 | terms.push(elem.name) 710 | 711 | // Extends 712 | var _extends = this.getSuperClasses(elem) 713 | if (_extends.length > 0) { 714 | terms.push('extends ' + _extends[0].name) 715 | } 716 | 717 | // Implements 718 | var _implements = this.getSuperInterfaces(elem) 719 | if (_implements.length > 0) { 720 | terms.push('implements ' + _implements.map(function (e) { return e.name }).join(', ')) 721 | } 722 | codeWriter.writeLine(terms.join(' ') + ' {') 723 | codeWriter.writeLine() 724 | codeWriter.indent() 725 | 726 | // Constructor 727 | this.writeConstructor(codeWriter, elem, options) 728 | codeWriter.writeLine() 729 | 730 | // Member Variables 731 | // (from attributes) 732 | for (i = 0, len = elem.attributes.length; i < len; i++) { 733 | this.writeMemberVariable(codeWriter, elem.attributes[i], options) 734 | codeWriter.writeLine() 735 | } 736 | // (from associations) 737 | var associations = app.repository.getRelationshipsOf(elem, function (rel) { 738 | return (rel instanceof type.UMLAssociation) 739 | }) 740 | for (i = 0, len = associations.length; i < len; i++) { 741 | var asso = associations[i] 742 | if (asso.end1.reference === elem && asso.end2.navigable === true) { 743 | this.writeMemberVariable(codeWriter, asso.end2, options) 744 | codeWriter.writeLine() 745 | } 746 | if (asso.end2.reference === elem && asso.end1.navigable === true) { 747 | this.writeMemberVariable(codeWriter, asso.end1, options) 748 | codeWriter.writeLine() 749 | } 750 | } 751 | 752 | // Methods 753 | for (i = 0, len = elem.operations.length; i < len; i++) { 754 | this.writeMethod(codeWriter, elem.operations[i], options, false, false) 755 | codeWriter.writeLine() 756 | } 757 | 758 | // Extends methods 759 | if (_extends.length > 0) { 760 | for (i = 0, len = _extends[0].operations.length; i < len; i++) { 761 | _modifiers = this.getModifiers(_extends[0].operations[i]) 762 | if (_modifiers.includes('abstract') === true) { 763 | this.writeMethod(codeWriter, _extends[0].operations[i], options, false, false) 764 | codeWriter.writeLine() 765 | } 766 | } 767 | } 768 | 769 | // Interface methods 770 | for (var j = 0; j < _implements.length; j++) { 771 | for (i = 0, len = _implements[j].operations.length; i < len; i++) { 772 | this.writeMethod(codeWriter, _implements[j].operations[i], options, false, false) 773 | codeWriter.writeLine() 774 | } 775 | } 776 | 777 | // Inner Definitions 778 | for (i = 0, len = elem.ownedElements.length; i < len; i++) { 779 | var def = elem.ownedElements[i] 780 | if (def instanceof type.UMLClass) { 781 | if (def.stereotype === 'annotationType') { 782 | this.writeAnnotationType(codeWriter, def, options) 783 | } else { 784 | this.writeClass(codeWriter, def, options) 785 | } 786 | codeWriter.writeLine() 787 | } else if (def instanceof type.UMLInterface) { 788 | this.writeInterface(codeWriter, def, options) 789 | codeWriter.writeLine() 790 | } else if (def instanceof type.UMLEnumeration) { 791 | this.writeEnum(codeWriter, def, options) 792 | codeWriter.writeLine() 793 | } 794 | } 795 | 796 | codeWriter.outdent() 797 | codeWriter.writeLine('}') 798 | } 799 | 800 | /** 801 | * Write Class 802 | * @param {StringWriter} codeWriter 803 | * @param {type.Model} elem 804 | * @param {Object} options 805 | */ 806 | writeEntity(codeWriter, elem, options) { 807 | var i, len 808 | var terms = [] 809 | 810 | // Doc 811 | var doc = elem.documentation.trim() 812 | if (app.project.getProject().author && app.project.getProject().author.length > 0) { 813 | doc += '\n@author ' + app.project.getProject().author 814 | } 815 | this.writeDoc(codeWriter, doc, options) 816 | 817 | if (elem.stereotype instanceof type.UMLClass && elem.stereotype.name === 'Entity') { 818 | codeWriter.import(elem.stereotype.name, codeHelper.getImportPath(elem, elem.stereotype)); 819 | if (options.tablePrefix) { 820 | codeWriter.writeLine(`@Entity('${options.tablePrefix}_${snakeCase(elem.name)}')`) 821 | } else { 822 | codeWriter.writeLine('@Entity()') 823 | } 824 | } 825 | 826 | var associations = app.repository.getRelationshipsOf(elem, (rel) => 827 | rel instanceof type.UMLAssociation && this.useTree(rel) 828 | ) 829 | if (associations.length > 0) { 830 | var asso = associations[0] 831 | var treeType = asso.name ? asso.name : 'materialized-path' 832 | codeWriter.import(asso.stereotype.name, codeHelper.getImportPath(elem, asso.stereotype)) 833 | codeWriter.writeLine(`@${asso.stereotype.name}('${treeType}')`) 834 | } 835 | 836 | terms.push('export') 837 | // Modifiers 838 | var _modifiers = this.getModifiers(elem, false) 839 | if (_modifiers.includes('abstract') !== true && elem.operations.some(function (op) { return op.isAbstract === true })) { 840 | _modifiers.push('abstract') 841 | } 842 | if (_modifiers.length > 0) { 843 | terms.push(_modifiers.join(' ')) 844 | } 845 | 846 | // Class 847 | terms.push('class') 848 | terms.push(elem.name) 849 | 850 | // Extends 851 | var _extends = this.getSuperClasses(elem) 852 | if (_extends.length > 0) { 853 | terms.push('extends ' + _extends[0].name) 854 | } 855 | 856 | // Implements 857 | var _implements = this.getSuperInterfaces(elem) 858 | if (_implements.length > 0) { 859 | terms.push('implements ' + _implements.map(function (e) { return e.name }).join(', ')) 860 | } 861 | codeWriter.writeLine(terms.join(' ') + ' {') 862 | codeWriter.writeLine() 863 | codeWriter.indent() 864 | 865 | // Constructor 866 | // this.writeConstructor(codeWriter, elem, options) 867 | // codeWriter.writeLine() 868 | 869 | // Member Variables 870 | // (from attributes) 871 | for (i = 0, len = elem.attributes.length; i < len; i++) { 872 | this.writeEntityColumn(codeWriter, elem.attributes[i], options) 873 | codeWriter.writeLine() 874 | } 875 | 876 | // (from associations) 877 | var associations = app.repository.getRelationshipsOf(elem, function (rel) { 878 | return (rel instanceof type.UMLAssociation) 879 | }) 880 | for (i = 0, len = associations.length; i < len; i++) { 881 | var asso = associations[i] 882 | if (asso.end1.reference === elem && asso.end2.navigable === true) { 883 | this.writeEntityRelation(codeWriter, asso, options, { 884 | element: elem, 885 | from: asso.end1, 886 | to: asso.end2, 887 | }) 888 | } 889 | if (asso.end2.reference === elem && asso.end1.navigable === true) { 890 | this.writeEntityRelation(codeWriter, asso, options, { 891 | element: elem, 892 | from: asso.end2, 893 | to: asso.end1 894 | }) 895 | } 896 | } 897 | 898 | // Methods 899 | for (i = 0, len = elem.operations.length; i < len; i++) { 900 | this.writeMethod(codeWriter, elem.operations[i], options, false, false) 901 | codeWriter.writeLine() 902 | } 903 | 904 | // Extends methods 905 | if (_extends.length > 0) { 906 | for (i = 0, len = _extends[0].operations.length; i < len; i++) { 907 | _modifiers = this.getModifiers(_extends[0].operations[i]) 908 | if (_modifiers.includes('abstract') === true) { 909 | this.writeMethod(codeWriter, _extends[0].operations[i], options, false, false) 910 | codeWriter.writeLine() 911 | } 912 | } 913 | } 914 | 915 | // Interface methods 916 | for (var j = 0; j < _implements.length; j++) { 917 | for (i = 0, len = _implements[j].operations.length; i < len; i++) { 918 | this.writeMethod(codeWriter, _implements[j].operations[i], options, false, false) 919 | codeWriter.writeLine() 920 | } 921 | } 922 | 923 | // Inner Definitions 924 | for (i = 0, len = elem.ownedElements.length; i < len; i++) { 925 | var def = elem.ownedElements[i] 926 | if (def instanceof type.UMLClass) { 927 | if (def.stereotype === 'annotationType') { 928 | this.writeAnnotationType(codeWriter, def, options) 929 | } else { 930 | this.writeClass(codeWriter, def, options) 931 | } 932 | codeWriter.writeLine() 933 | } else if (def instanceof type.UMLInterface) { 934 | this.writeInterface(codeWriter, def, options) 935 | codeWriter.writeLine() 936 | } else if (def instanceof type.UMLEnumeration) { 937 | this.writeEnum(codeWriter, def, options) 938 | codeWriter.writeLine() 939 | } 940 | } 941 | 942 | codeWriter.outdent() 943 | codeWriter.writeLine('}') 944 | codeWriter.writeLine() 945 | } 946 | 947 | /** 948 | * Write Class 949 | * @param {StringWriter} codeWriter 950 | * @param {type.Model} elem 951 | * @param {Object} options 952 | */ 953 | writeModel(codeWriter, elem, options) { 954 | var i, len 955 | var terms = [] 956 | 957 | // Doc 958 | var doc = elem.documentation.trim() 959 | if (app.project.getProject().author && app.project.getProject().author.length > 0) { 960 | doc += '\n@author ' + app.project.getProject().author 961 | } 962 | this.writeDoc(codeWriter, doc, options) 963 | 964 | terms.push('export') 965 | // Modifiers 966 | var _modifiers = this.getModifiers(elem, false) 967 | if (_modifiers.includes('abstract') !== true && elem.operations.some(function (op) { return op.isAbstract === true })) { 968 | _modifiers.push('abstract') 969 | } 970 | if (_modifiers.length > 0) { 971 | terms.push(_modifiers.join(' ')) 972 | } 973 | 974 | // Class 975 | terms.push('class') 976 | if (elem.stereotype === 'FieldSet') { 977 | terms.push(elem.name) 978 | } else { 979 | terms.push(elem.name + 'Model') 980 | } 981 | 982 | // Extends 983 | var _extends = this.getSuperClasses(elem) 984 | if (_extends.length > 0) { 985 | terms.push('extends ' + _extends[0].name) 986 | } 987 | 988 | // Implements 989 | var _implements = this.getSuperInterfaces(elem) 990 | if (_implements.length > 0) { 991 | terms.push('implements ' + _implements.map(function (e) { return e.name }).join(', ')) 992 | } 993 | codeWriter.writeLine(terms.join(' ') + ' {') 994 | codeWriter.writeLine() 995 | codeWriter.indent() 996 | 997 | // Constructor 998 | // this.writeConstructor(codeWriter, elem, options) 999 | // codeWriter.writeLine() 1000 | 1001 | // Member Variables 1002 | // (from attributes) 1003 | 1004 | for (i = 0, len = elem.attributes.length; i < len; i++) { 1005 | let attr = elem.attributes[i] 1006 | if (attr.type instanceof type.UMLModelElement && attr.type.name.length > 0) { 1007 | if (attr.type.stereotype === 'FieldSet') { 1008 | attr.type.isModel = true 1009 | } 1010 | codeWriter.import(attr.type.name, codeHelper.getImportPath(attr, attr.type)) 1011 | if (attr.type.isModel) { 1012 | delete attr.type.isModel 1013 | } 1014 | 1015 | } 1016 | 1017 | if (attr.name.endsWith('?')) { 1018 | codeWriter.import('ApiModelPropertyOptional', '@nestjs/swagger') 1019 | codeWriter.writeLine('@ApiModelPropertyOptional()') 1020 | } else { 1021 | codeWriter.import('ApiModelProperty', '@nestjs/swagger') 1022 | codeWriter.writeLine('@ApiModelProperty()') 1023 | } 1024 | 1025 | this.writeMemberVariable(codeWriter, attr, options) 1026 | codeWriter.writeLine() 1027 | } 1028 | 1029 | // (from associations) 1030 | var associations = app.repository.getRelationshipsOf(elem, function (rel) { 1031 | return (rel instanceof type.UMLAssociation) 1032 | }) 1033 | for (i = 0, len = associations.length; i < len; i++) { 1034 | var asso = associations[i] 1035 | if (asso.end1.reference === elem && asso.end2.navigable === true) { 1036 | this.writeModelRelation(codeWriter, { 1037 | from: asso.end1, 1038 | to: asso.end2 1039 | }, options) 1040 | } 1041 | if (asso.end2.reference === elem && asso.end1.navigable === true) { 1042 | this.writeModelRelation(codeWriter, { 1043 | from: asso.end2, 1044 | to: asso.end1 1045 | }, options) 1046 | } 1047 | } 1048 | 1049 | // Methods 1050 | for (i = 0, len = elem.operations.length; i < len; i++) { 1051 | this.writeMethod(codeWriter, elem.operations[i], options, false, false) 1052 | codeWriter.writeLine() 1053 | } 1054 | 1055 | // Extends methods 1056 | if (_extends.length > 0) { 1057 | for (i = 0, len = _extends[0].operations.length; i < len; i++) { 1058 | _modifiers = this.getModifiers(_extends[0].operations[i]) 1059 | if (_modifiers.includes('abstract') === true) { 1060 | this.writeMethod(codeWriter, _extends[0].operations[i], options, false, false) 1061 | codeWriter.writeLine() 1062 | } 1063 | } 1064 | } 1065 | 1066 | // Interface methods 1067 | for (var j = 0; j < _implements.length; j++) { 1068 | for (i = 0, len = _implements[j].operations.length; i < len; i++) { 1069 | this.writeMethod(codeWriter, _implements[j].operations[i], options, false, false) 1070 | codeWriter.writeLine() 1071 | } 1072 | } 1073 | 1074 | // Inner Definitions 1075 | for (i = 0, len = elem.ownedElements.length; i < len; i++) { 1076 | var def = elem.ownedElements[i] 1077 | if (def instanceof type.UMLClass) { 1078 | if (def.stereotype === 'annotationType') { 1079 | this.writeAnnotationType(codeWriter, def, options) 1080 | } else { 1081 | this.writeClass(codeWriter, def, options) 1082 | } 1083 | codeWriter.writeLine() 1084 | } else if (def instanceof type.UMLInterface) { 1085 | this.writeInterface(codeWriter, def, options) 1086 | codeWriter.writeLine() 1087 | } else if (def instanceof type.UMLEnumeration) { 1088 | this.writeEnum(codeWriter, def, options) 1089 | codeWriter.writeLine() 1090 | } 1091 | } 1092 | 1093 | codeWriter.outdent() 1094 | codeWriter.writeLine('}') 1095 | codeWriter.writeLine() 1096 | } 1097 | 1098 | /** 1099 | * Write Class 1100 | * @param {StringWriter} codeWriter 1101 | * @param {type.Model} elem 1102 | * @param {Object} options 1103 | */ 1104 | writeModule(codeWriter, elem, options) { 1105 | var i, len 1106 | var terms = [] 1107 | 1108 | // Doc 1109 | var doc = elem.documentation.trim() 1110 | if (app.project.getProject().author && app.project.getProject().author.length > 0) { 1111 | doc += '\n@author ' + app.project.getProject().author 1112 | } 1113 | this.writeDoc(codeWriter, doc, options) 1114 | 1115 | codeWriter.import(elem.stereotype.name, codeHelper.getImportPath(elem, elem.stereotype)); 1116 | 1117 | codeWriter.import('TypeOrmModule', '@nestjs/typeorm') 1118 | this.entities.forEach(e => codeWriter.import(e.name, codeHelper.getImportPath(elem, e))) 1119 | this.services.forEach(e => codeWriter.import(e.name, codeHelper.getImportPath(elem, e))) 1120 | this.controllers.forEach(e => codeWriter.import(e.name, codeHelper.getImportPath(elem, e))) 1121 | 1122 | codeWriter.writeLine('@Module({') 1123 | codeWriter.indent() 1124 | if (this.entities.length > 0) { 1125 | codeWriter.writeLine('imports: [') 1126 | codeWriter.indent() 1127 | codeWriter.writeLine('TypeOrmModule.forFeature([') 1128 | codeWriter.indent() 1129 | this.entities.forEach(e => codeWriter.writeLine(e.name + ',')) 1130 | codeWriter.outdent() 1131 | codeWriter.writeLine(']),') 1132 | codeWriter.outdent() 1133 | codeWriter.writeLine('],') 1134 | } 1135 | if (this.services.length > 0) { 1136 | codeWriter.writeLine('providers: [') 1137 | codeWriter.indent() 1138 | this.services.forEach(e => codeWriter.writeLine(e.name + ',')) 1139 | codeWriter.outdent() 1140 | codeWriter.writeLine('],') 1141 | } 1142 | if (this.controllers.length > 0) { 1143 | codeWriter.writeLine('controllers: [') 1144 | codeWriter.indent() 1145 | this.controllers.forEach(e => codeWriter.writeLine(e.name + ',')) 1146 | codeWriter.outdent() 1147 | codeWriter.writeLine('],') 1148 | } 1149 | codeWriter.outdent() 1150 | codeWriter.writeLine('})') 1151 | 1152 | terms.push('export') 1153 | 1154 | // Class 1155 | terms.push('class') 1156 | terms.push(capitalize(camelCase(elem.name)) + 'Module') 1157 | 1158 | // Extends 1159 | var _extends = this.getSuperClasses(elem) 1160 | if (_extends.length > 0) { 1161 | terms.push('extends ' + _extends[0].name) 1162 | } 1163 | 1164 | // Implements 1165 | var _implements = this.getSuperInterfaces(elem) 1166 | if (_implements.length > 0) { 1167 | terms.push('implements ' + _implements.map(function (e) { return e.name }).join(', ')) 1168 | } 1169 | codeWriter.writeLine(terms.join(' ') + ' {') 1170 | codeWriter.writeLine() 1171 | codeWriter.writeLine('}') 1172 | codeWriter.writeLine() 1173 | } 1174 | 1175 | /** 1176 | * Write Class 1177 | * @param {StringWriter} codeWriter 1178 | * @param {type.Model} elem 1179 | * @param {Object} options 1180 | */ 1181 | writeCrudController(codeWriter, elem, options) { 1182 | var i, len 1183 | var terms = [] 1184 | 1185 | // Doc 1186 | var doc = elem.documentation.trim() 1187 | if (app.project.getProject().author && app.project.getProject().author.length > 0) { 1188 | doc += '\n@author ' + app.project.getProject().author 1189 | } 1190 | this.writeDoc(codeWriter, doc, options) 1191 | 1192 | codeWriter.import(elem.stereotype.name, codeHelper.getImportPath(elem, elem.stereotype)); 1193 | codeWriter.import('Crud', '@nestjsx/crud') 1194 | codeWriter.import('ApiUseTags', '@nestjs/swagger') 1195 | 1196 | var associations = app.repository.getRelationshipsOf(elem, function (rel) { 1197 | return (rel instanceof type.UMLAssociation) 1198 | }) 1199 | 1200 | let crudSvc 1201 | let crudEntity 1202 | let svcs = associations 1203 | .map(asso => asso.end2.reference) 1204 | .map(svc => { 1205 | codeWriter.import(svc.name, codeHelper.getImportPath(elem, svc)); 1206 | return svc 1207 | }) 1208 | .map(svc => { 1209 | var generalizations = app.repository.getRelationshipsOf(svc, function (rel) { 1210 | return (rel instanceof type.UMLGeneralization 1211 | && rel.source === svc 1212 | && rel.target.name === 'TypeOrmCrudService') 1213 | }) 1214 | if (generalizations.length > 0) { 1215 | crudSvc = crudSvc ? crudSvc : svc 1216 | crudEntity = crudEntity ? crudEntity : generalizations[0].stereotype 1217 | } 1218 | return svc 1219 | }) 1220 | 1221 | let modelName = crudEntity.name + 'Model' 1222 | codeWriter.writeLine('@Crud({') 1223 | if (crudEntity) { 1224 | crudEntity.isModel = true 1225 | codeWriter.import(modelName, codeHelper.getImportPath(elem, crudEntity)); 1226 | delete crudEntity.isModel 1227 | codeWriter.indent() 1228 | codeWriter.writeLine('model: {') 1229 | codeWriter.indent() 1230 | codeWriter.writeLine(`type: ${modelName},`) 1231 | codeWriter.outdent() 1232 | codeWriter.writeLine('},') 1233 | codeWriter.outdent() 1234 | } 1235 | codeWriter.writeLine('})') 1236 | 1237 | codeWriter.writeLine(`@ApiUseTags('${codeHelper.getModuleName(elem)}')`) 1238 | codeWriter.writeLine(`@Controller('${kebabCase(pluralize(crudEntity.name))}')`) 1239 | 1240 | terms.push('export') 1241 | terms.push('class') 1242 | terms.push(elem.name) 1243 | 1244 | if (crudEntity) { 1245 | codeWriter.import('CrudController', '@nestjsx/crud') 1246 | terms.push('implements') 1247 | terms.push(`CrudController<${modelName}> `) 1248 | } 1249 | 1250 | codeWriter.writeLine(terms.join(' ') + ' {') 1251 | codeWriter.indent() 1252 | if (svcs.length > 0) { 1253 | codeWriter.writeLine('constructor(') 1254 | codeWriter.indent() 1255 | svcs.map(svc => `${svc === crudSvc ? 'public' : 'private'} readonly ${svc === crudSvc ? 'service' : camelCase(svc.name)}: ${svc.name},`) 1256 | .join(',@') 1257 | .split('@') 1258 | .forEach(param => codeWriter.writeLine(param)) 1259 | codeWriter.outdent() 1260 | codeWriter.writeLine(') { }') 1261 | } else { 1262 | codeWriter.writeLine('constructor() { }') 1263 | } 1264 | if (crudEntity) { 1265 | codeWriter.writeLine(); 1266 | codeWriter.writeLine(`get base(): CrudController<${modelName}> {`) 1267 | codeWriter.indent() 1268 | codeWriter.writeLine('return this;') 1269 | codeWriter.outdent() 1270 | codeWriter.writeLine('}') 1271 | } 1272 | 1273 | codeWriter.outdent() 1274 | codeWriter.writeLine('}') 1275 | codeWriter.writeLine() 1276 | } 1277 | 1278 | /** 1279 | * Write Class 1280 | * @param {StringWriter} codeWriter 1281 | * @param {type.Model} elem 1282 | * @param {Object} options 1283 | */ 1284 | writeCrudService(codeWriter, elem, options) { 1285 | var i, len 1286 | var terms = [] 1287 | 1288 | // Doc 1289 | var doc = elem.documentation.trim() 1290 | if (app.project.getProject().author && app.project.getProject().author.length > 0) { 1291 | doc += '\n@author ' + app.project.getProject().author 1292 | } 1293 | this.writeDoc(codeWriter, doc, options) 1294 | 1295 | var generalizations = app.repository.getRelationshipsOf(elem, function (rel) { 1296 | return (rel instanceof type.UMLGeneralization && rel.source === elem) 1297 | }) 1298 | var entity = generalizations[0].stereotype 1299 | codeWriter.import(entity.name, codeHelper.getImportPath(elem, entity)); 1300 | codeWriter.import(elem.stereotype.name, codeHelper.getImportPath(elem, elem.stereotype)); 1301 | codeWriter.import('InjectRepository', '@nestjs/typeorm') 1302 | codeWriter.import('TypeOrmCrudService', '@nestjsx/crud-typeorm') 1303 | 1304 | codeWriter.writeLine('@Injectable()') 1305 | 1306 | terms.push('export') 1307 | 1308 | // Class 1309 | terms.push('class') 1310 | terms.push(elem.name) 1311 | 1312 | // Extends 1313 | if (generalizations.length > 0) { 1314 | terms.push(`extends ${generalizations[0].target.name}<${entity.name}>`) 1315 | } 1316 | 1317 | codeWriter.writeLine(terms.join(' ') + ' {') 1318 | codeWriter.indent() 1319 | codeWriter.writeLine(`constructor(@InjectRepository(${entity.name}) repo) {`) 1320 | codeWriter.indent() 1321 | codeWriter.writeLine('super(repo);') 1322 | codeWriter.outdent() 1323 | codeWriter.writeLine('}') 1324 | codeWriter.outdent() 1325 | codeWriter.writeLine('}') 1326 | } 1327 | 1328 | /** 1329 | * Write Interface 1330 | * @param {StringWriter} codeWriter 1331 | * @param {type.Model} elem 1332 | * @param {Object} options 1333 | */ 1334 | writeInterface(codeWriter, elem, options) { 1335 | var i, len 1336 | var terms = [] 1337 | 1338 | // Doc 1339 | this.writeDoc(codeWriter, elem.documentation, options) 1340 | 1341 | // Modifiers 1342 | var visibility = this.getVisibility(elem) 1343 | if (visibility) { 1344 | terms.push(visibility) 1345 | } 1346 | 1347 | // Interface 1348 | terms.push('interface') 1349 | terms.push(elem.name) 1350 | 1351 | // Extends 1352 | var _extends = this.getSuperClasses(elem) 1353 | if (_extends.length > 0) { 1354 | terms.push('extends ' + _extends.map(function (e) { return e.name }).join(', ')) 1355 | } 1356 | codeWriter.writeLine(terms.join(' ') + ' {') 1357 | codeWriter.writeLine() 1358 | codeWriter.indent() 1359 | 1360 | // Member Variables 1361 | // (from attributes) 1362 | for (i = 0, len = elem.attributes.length; i < len; i++) { 1363 | this.writeMemberVariable(codeWriter, elem.attributes[i], options) 1364 | codeWriter.writeLine() 1365 | } 1366 | // (from associations) 1367 | var associations = app.repository.getRelationshipsOf(elem, function (rel) { 1368 | return (rel instanceof type.UMLAssociation) 1369 | }) 1370 | for (i = 0, len = associations.length; i < len; i++) { 1371 | var asso = associations[i] 1372 | if (asso.end1.reference === elem && asso.end2.navigable === true) { 1373 | this.writeMemberVariable(codeWriter, asso.end2, options) 1374 | codeWriter.writeLine() 1375 | } 1376 | if (asso.end2.reference === elem && asso.end1.navigable === true) { 1377 | this.writeMemberVariable(codeWriter, asso.end1, options) 1378 | codeWriter.writeLine() 1379 | } 1380 | } 1381 | 1382 | // Methods 1383 | for (i = 0, len = elem.operations.length; i < len; i++) { 1384 | this.writeMethod(codeWriter, elem.operations[i], options, true, false) 1385 | codeWriter.writeLine() 1386 | } 1387 | 1388 | // Inner Definitions 1389 | for (i = 0, len = elem.ownedElements.length; i < len; i++) { 1390 | var def = elem.ownedElements[i] 1391 | if (def instanceof type.UMLClass) { 1392 | if (def.stereotype === 'annotationType') { 1393 | this.writeAnnotationType(codeWriter, def, options) 1394 | } else { 1395 | this.writeClass(codeWriter, def, options) 1396 | } 1397 | codeWriter.writeLine() 1398 | } else if (def instanceof type.UMLInterface) { 1399 | this.writeInterface(codeWriter, def, options) 1400 | codeWriter.writeLine() 1401 | } else if (def instanceof type.UMLEnumeration) { 1402 | this.writeEnum(codeWriter, def, options) 1403 | codeWriter.writeLine() 1404 | } 1405 | } 1406 | 1407 | codeWriter.outdent() 1408 | codeWriter.writeLine('}') 1409 | } 1410 | 1411 | /** 1412 | * Write Enum 1413 | * @param {StringWriter} codeWriter 1414 | * @param {type.Model} elem 1415 | * @param {Object} options 1416 | */ 1417 | writeEnum(codeWriter, elem, options) { 1418 | var i, len 1419 | var terms = [] 1420 | // Doc 1421 | this.writeDoc(codeWriter, elem.documentation, options) 1422 | 1423 | // Modifiers 1424 | var visibility = this.getVisibility(elem) 1425 | if (visibility) { 1426 | terms.push(visibility) 1427 | } 1428 | // Enum 1429 | terms.push('enum') 1430 | terms.push(elem.name) 1431 | 1432 | codeWriter.writeLine(terms.join(' ') + ' {') 1433 | codeWriter.indent() 1434 | 1435 | // Literals 1436 | for (i = 0, len = elem.literals.length; i < len; i++) { 1437 | codeWriter.writeLine(elem.literals[i].name + (i < elem.literals.length - 1 ? ',' : '')) 1438 | } 1439 | 1440 | codeWriter.outdent() 1441 | codeWriter.writeLine('}') 1442 | } 1443 | 1444 | /** 1445 | * Write AnnotationType 1446 | * @param {StringWriter} codeWriter 1447 | * @param {type.Model} elem 1448 | * @param {Object} options 1449 | */ 1450 | writeAnnotationType(codeWriter, elem, options) { 1451 | var i, len 1452 | var terms = [] 1453 | 1454 | // Doc 1455 | var doc = elem.documentation.trim() 1456 | if (app.project.getProject().author && app.project.getProject().author.length > 0) { 1457 | doc += '\n@author ' + app.project.getProject().author 1458 | } 1459 | this.writeDoc(codeWriter, doc, options) 1460 | 1461 | // Modifiers 1462 | var _modifiers = this.getModifiers(elem) 1463 | if (_modifiers.includes('abstract') !== true && elem.operations.some(function (op) { return op.isAbstract === true })) { 1464 | _modifiers.push('abstract') 1465 | } 1466 | if (_modifiers.length > 0) { 1467 | terms.push(_modifiers.join(' ')) 1468 | } 1469 | 1470 | // AnnotationType 1471 | terms.push('@interface') 1472 | terms.push(elem.name) 1473 | 1474 | codeWriter.writeLine(terms.join(' ') + ' {') 1475 | codeWriter.writeLine() 1476 | codeWriter.indent() 1477 | 1478 | // Member Variables 1479 | for (i = 0, len = elem.attributes.length; i < len; i++) { 1480 | this.writeMemberVariable(codeWriter, elem.attributes[i], options) 1481 | codeWriter.writeLine() 1482 | } 1483 | 1484 | // Methods 1485 | for (i = 0, len = elem.operations.length; i < len; i++) { 1486 | this.writeMethod(codeWriter, elem.operations[i], options, true, true) 1487 | codeWriter.writeLine() 1488 | } 1489 | 1490 | // Extends methods 1491 | var _extends = this.getSuperClasses(elem) 1492 | if (_extends.length > 0) { 1493 | for (i = 0, len = _extends[0].operations.length; i < len; i++) { 1494 | _modifiers = this.getModifiers(_extends[0].operations[i]) 1495 | if (_modifiers.includes('abstract') === true) { 1496 | this.writeMethod(codeWriter, _extends[0].operations[i], options, false, false) 1497 | codeWriter.writeLine() 1498 | } 1499 | } 1500 | } 1501 | 1502 | // Inner Definitions 1503 | for (i = 0, len = elem.ownedElements.length; i < len; i++) { 1504 | var def = elem.ownedElements[i] 1505 | if (def instanceof type.UMLClass) { 1506 | if (def.stereotype === 'annotationType') { 1507 | this.writeAnnotationType(codeWriter, def, options) 1508 | } else { 1509 | this.writeClass(codeWriter, def, options) 1510 | } 1511 | codeWriter.writeLine() 1512 | } else if (def instanceof type.UMLInterface) { 1513 | this.writeInterface(codeWriter, def, options) 1514 | codeWriter.writeLine() 1515 | } else if (def instanceof type.UMLEnumeration) { 1516 | this.writeEnum(codeWriter, def, options) 1517 | codeWriter.writeLine() 1518 | } 1519 | } 1520 | 1521 | codeWriter.outdent() 1522 | codeWriter.writeLine('}') 1523 | } 1524 | } 1525 | 1526 | /** 1527 | * Generate 1528 | * @param {type.Model} baseModel 1529 | * @param {string} basePath 1530 | * @param {Object} options 1531 | */ 1532 | function generate(baseModel, basePath, options) { 1533 | var nestCodeGenerator = new NestCodeGenerator(baseModel, basePath) 1534 | nestCodeGenerator.generate(baseModel, basePath, options) 1535 | } 1536 | 1537 | exports.generate = generate 1538 | -------------------------------------------------------------------------------- /lib/code-helper.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const kebabCase = require('lodash.kebabcase') 3 | const camelCase = require('lodash.camelcase') 4 | const snakeCase = require('lodash.snakecase') 5 | const pluralize = require('pluralize') 6 | const capitalize = require('lodash.capitalize') 7 | 8 | exports.CodeHelper = class CodeHelper { 9 | getFileName(elem) { 10 | let fileName = '' 11 | if (elem.stereotype instanceof type.UMLClass) { 12 | if (elem.isModel) { 13 | fileName = kebabCase(elem.name) + '.model' 14 | } else if (elem.stereotype.name === 'Entity') { 15 | fileName = kebabCase(elem.name) + '.entity' 16 | } else if (elem.stereotype.name === 'Module') { 17 | fileName = kebabCase(elem.name) + '.module' 18 | } else if (elem.stereotype.name === 'Injectable') { 19 | fileName = kebabCase(elem.name.replace('Service', '')) + '.service' 20 | } else if (elem.stereotype.name === 'Controller') { 21 | fileName = kebabCase(elem.name.replace('Controller', '')) + '.controller' 22 | } 23 | } else if (elem.stereotype === 'FieldSet') { 24 | fileName = kebabCase(elem.name.replace('FieldSet', '')) + '.fieldset' 25 | } 26 | return fileName 27 | } 28 | 29 | getModuleName(elem) { 30 | if (!elem || elem instanceof type.UMLModel) { 31 | return '' 32 | } 33 | 34 | if (elem instanceof type.UMLPackage 35 | && elem.stereotype instanceof type.UMLClass 36 | && elem.stereotype.name === 'Module') { 37 | return elem.name 38 | } else { 39 | return this.getModuleName(elem._parent) 40 | } 41 | } 42 | 43 | getImportPath(from, to) { 44 | const fromPath = this.getPackagePath(from) 45 | const toPath = this.getPackagePath(to) 46 | 47 | if (toPath.startsWith('./node_modules')) { 48 | return path.relative('./node_modules', toPath) 49 | } else { 50 | let basePath = path.relative(fromPath, toPath) 51 | if (basePath && !basePath.startsWith('..')) { 52 | basePath = './' + basePath 53 | } 54 | 55 | if (!basePath) { 56 | basePath = '.' 57 | } 58 | return basePath + '/' + this.getFileName(to) 59 | } 60 | } 61 | 62 | getPackagePath(elem, child) { 63 | if (!elem || elem instanceof type.UMLModel) { 64 | return '.' 65 | } 66 | 67 | var parentPath = this.getPackagePath(elem._parent, elem) 68 | if (elem instanceof type.UMLPackage) { 69 | if (parentPath === './node_modules' && { 70 | 'nestjs/common': true, 71 | 'nestjs/typeorm': true, 72 | 'nestjsx/crud': true, 73 | 'nestjsx/crud-typeorm': true, 74 | }[elem.name]) { 75 | return parentPath + '/@' + elem.name 76 | } 77 | else { 78 | if (child && child.isModel) { 79 | return parentPath + '/models' 80 | } else { 81 | return parentPath + '/' + elem.name 82 | } 83 | } 84 | } else { 85 | return parentPath 86 | } 87 | } 88 | 89 | getSelector(elem) { 90 | if (!elem._parent) { 91 | return '' 92 | } 93 | 94 | return this.getSelector(elem._parent) + '::' + `@${elem.constructor.name}[name=${elem.name}]` 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/code-writer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2018 MKLab. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | /** 25 | * CodeWriter 26 | */ 27 | exports.CodeWriter = class CodeWriter { 28 | /** 29 | * @constructor 30 | */ 31 | constructor(indentString) { 32 | /** @member {Array.} lines */ 33 | this.lines = [] 34 | 35 | /** @member {string} indentString */ 36 | this.indentString = indentString || ' ' // default 4 spaces 37 | 38 | /** @member {Array.} indentations */ 39 | this.indentations = [] 40 | 41 | this.imports = {} 42 | } 43 | 44 | /** 45 | * Indent 46 | */ 47 | indent() { 48 | this.indentations.push(this.indentString) 49 | } 50 | 51 | /** 52 | * Outdent 53 | */ 54 | outdent() { 55 | this.indentations.splice(this.indentations.length - 1, 1) 56 | } 57 | 58 | import(type, pkg) { 59 | if (!this.imports[pkg]) { 60 | this.imports[pkg] = [type] 61 | } else if (!this.imports[pkg].includes(type)) { 62 | this.imports[pkg].push(type) 63 | } 64 | } 65 | 66 | /** 67 | * Write a line 68 | * @param {string} line 69 | */ 70 | writeLine(line) { 71 | if (line) { 72 | this.lines.push(this.indentations.join('') + line) 73 | } else { 74 | this.lines.push('') 75 | } 76 | } 77 | 78 | /** 79 | * Return as all string data 80 | * @return {string} 81 | */ 82 | getData() { 83 | var impStr = Object 84 | .keys(this.imports) 85 | .map(pkg => `import { ${this.imports[pkg].join(', ')} } from '${pkg}';`) 86 | .join('\n') 87 | impStr = impStr ? impStr + '\n' : impStr 88 | return impStr + this.lines.join('\n') 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /lib/crud-generator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 MKLab. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | const { CodeHelper } = require('./code-helper') 25 | const codeHelper = new CodeHelper() 26 | 27 | /** 28 | * Java Code Generator 29 | */ 30 | class NestCodeGenerator { 31 | 32 | /** 33 | * @constructor 34 | * 35 | * @param {type.UMLPackage} baseModel 36 | * @param {string} basePath generated files and directories to be placed 37 | */ 38 | constructor(baseModel, basePath) { 39 | /** @member {type.Model} */ 40 | this.baseModel = baseModel 41 | 42 | /** @member {string} */ 43 | this.basePath = basePath 44 | this.entities = [] 45 | } 46 | 47 | /** 48 | * Generate codes from a given element 49 | * @param {type.Model} elem 50 | * @param {string} basePath 51 | * @param {Object} options 52 | */ 53 | generate(elem, basePath, options) { 54 | var fullPath 55 | var pkg 56 | 57 | // Package 58 | if (elem instanceof type.UMLPackage) { 59 | if (Array.isArray(elem.ownedElements)) { 60 | elem.ownedElements.forEach(child => { 61 | return this.generate(child, fullPath, options) 62 | }) 63 | } 64 | if (elem.stereotype instanceof type.UMLClass && elem.stereotype.name === 'Module') { 65 | if (this.entities.length > 0) { 66 | pkg = this.createPackage(elem, 'services'); 67 | this.createCrudServices(this.entities, pkg) 68 | 69 | pkg = this.createPackage(elem, 'controllers'); 70 | this.createCrudControllers(this.entities, pkg) 71 | } 72 | 73 | this.entities = [] 74 | } 75 | } else if (elem instanceof type.UMLClass) { 76 | if ((elem.stereotype instanceof type.UMLClass 77 | && elem.stereotype.name === 'Entity')) { 78 | this.entities.push(elem) 79 | // Class 80 | } 81 | } 82 | } 83 | 84 | createPackage(parent, name) { 85 | var selector = `${codeHelper.getSelector(parent)}::@UMLPackage[name=${name}]` 86 | var [pkg] = app.repository.select(selector) 87 | if (!pkg) { 88 | pkg = app.factory.createModel({ 89 | id: 'UMLPackage', 90 | parent: parent, 91 | modelInitializer: function (elem) { 92 | elem.name = name 93 | } 94 | }) 95 | } 96 | return pkg 97 | } 98 | 99 | createCrudControllers(entities, pkg) { 100 | let controller = app.repository.select('Controller')[0] 101 | 102 | return entities.map(entity => { 103 | var selector = `${codeHelper.getSelector(pkg)}::@UMLClass[name=${entity.name + 'Controller'}]` 104 | var [classElem] = app.repository.select(selector) 105 | if (!classElem) { 106 | let service = app.repository.select(entity.name + 'Service')[0] 107 | classElem = app.factory.createModel({ 108 | id: 'UMLClass', 109 | parent: pkg, 110 | modelInitializer: function (elem) { 111 | elem.name = entity.name + 'Controller' 112 | elem.stereotype = controller 113 | 114 | let association = new type.UMLAssociation() 115 | association._parent = elem 116 | association.end1.reference = elem 117 | association.end1.navigable = false 118 | association.end2.reference = service 119 | elem.ownedElements.push(association) 120 | } 121 | }) 122 | } 123 | return classElem 124 | }) 125 | } 126 | 127 | createCrudServices(entities, pkg) { 128 | let injectable = app.repository.select('Injectable')[0] 129 | let typeOrmCrudService = app.repository.select('TypeOrmCrudService')[0] 130 | 131 | return entities.map(entity => { 132 | var selector = `${codeHelper.getSelector(pkg)}::@UMLClass[name=${entity.name + 'Service'}]` 133 | var [classElem] = app.repository.select(selector) 134 | if (!classElem) { 135 | classElem = app.factory.createModel({ 136 | id: 'UMLClass', 137 | parent: pkg, 138 | modelInitializer: function (elem) { 139 | elem.name = entity.name + 'Service' 140 | elem.stereotype = injectable 141 | 142 | let generalization = new type.UMLGeneralization() 143 | generalization._parent = elem 144 | generalization.source = elem 145 | generalization.target = typeOrmCrudService 146 | generalization.stereotype = entity 147 | elem.ownedElements.push(generalization) 148 | } 149 | }) 150 | } 151 | return classElem 152 | }) 153 | } 154 | } 155 | 156 | /** 157 | * Generate 158 | * @param {type.Model} baseModel 159 | * @param {string} basePath 160 | * @param {Object} options 161 | */ 162 | function generate(baseModel, basePath, options) { 163 | var nestCodeGenerator = new NestCodeGenerator(baseModel, basePath) 164 | nestCodeGenerator.generate(baseModel, basePath, options) 165 | } 166 | 167 | exports.generate = generate 168 | -------------------------------------------------------------------------------- /lib/meta-generator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019 MKLab. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | const { CodeHelper } = require('./code-helper') 25 | const codeHelper = new CodeHelper() 26 | 27 | /** 28 | * Java Code Generator 29 | */ 30 | class NestCodeGenerator { 31 | 32 | /** 33 | * @constructor 34 | * 35 | * @param {type.UMLPackage} baseModel 36 | * @param {string} basePath generated files and directories to be placed 37 | */ 38 | constructor(baseModel, basePath) { 39 | /** @member {type.Model} */ 40 | this.baseModel = baseModel 41 | 42 | /** @member {string} */ 43 | this.basePath = basePath 44 | this.entities = [] 45 | } 46 | 47 | /** 48 | * Generate codes from a given element 49 | * @param {type.Model} elem 50 | * @param {string} basePath 51 | * @param {Object} options 52 | */ 53 | generate(elem, basePath, options) { 54 | var meta = { 55 | id: 'UMLPackage', 56 | name: 'node_modules', 57 | children: [ 58 | { 59 | id: 'UMLPackage', 60 | name: 'nestjs/common', 61 | children: [ 62 | { 63 | id: 'UMLClass', 64 | name: 'Injectable', 65 | }, 66 | { 67 | id: 'UMLClass', 68 | name: 'Module', 69 | }, 70 | { 71 | id: 'UMLClass', 72 | name: 'Controller', 73 | }, 74 | ] 75 | }, 76 | { 77 | id: 'UMLPackage', 78 | name: 'nestjs/typeorm', 79 | children: [ 80 | { 81 | id: 'UMLClass', 82 | name: 'InjectRepository', 83 | }, 84 | ] 85 | }, 86 | { 87 | id: 'UMLPackage', 88 | name: 'nestjsx/crud', 89 | children: [ 90 | { 91 | id: 'UMLClass', 92 | name: 'Crud', 93 | }, 94 | { 95 | id: 'UMLClass', 96 | name: 'CrudController', 97 | } 98 | ] 99 | }, 100 | { 101 | id: 'UMLPackage', 102 | name: 'nestjsx/crud-typeorm', 103 | children: [ 104 | { 105 | id: 'UMLClass', 106 | name: 'TypeOrmCrudService', 107 | }, 108 | ] 109 | }, 110 | { 111 | id: 'UMLPackage', 112 | name: 'typeorm', 113 | children: [ 114 | { 115 | id: 'UMLClass', 116 | name: 'Column', 117 | }, 118 | { 119 | id: 'UMLClass', 120 | name: 'CreateDateColumn', 121 | }, 122 | { 123 | id: 'UMLClass', 124 | name: 'Entity', 125 | }, 126 | { 127 | id: 'UMLClass', 128 | name: 'OneToMany', 129 | }, 130 | { 131 | id: 'UMLClass', 132 | name: 'PrimaryColumn', 133 | }, 134 | { 135 | id: 'UMLClass', 136 | name: 'VersionColumn', 137 | }, 138 | { 139 | id: 'UMLClass', 140 | name: 'ManyToOne', 141 | }, 142 | { 143 | id: 'UMLClass', 144 | name: 'ManyToMany', 145 | }, 146 | { 147 | id: 'UMLClass', 148 | name: 'OneToOne', 149 | }, 150 | { 151 | id: 'UMLClass', 152 | name: 'UpdateDateColumn', 153 | }, 154 | { 155 | id: 'UMLClass', 156 | name: 'JoinColumn', 157 | }, 158 | { 159 | id: 'UMLClass', 160 | name: 'JoinTable', 161 | }, 162 | { 163 | id: 'UMLClass', 164 | name: 'Tree', 165 | }, 166 | ] 167 | }, 168 | ] 169 | } 170 | 171 | this.createModel(elem, meta) 172 | } 173 | 174 | createModel(parent, child) { 175 | var selector = `${codeHelper.getSelector(parent)}::@${child.id}[name=${child.name}]` 176 | var [nextParent] = app.repository.select(selector) 177 | if (!nextParent) { 178 | nextParent = app.factory.createModel({ 179 | id: child.id, 180 | parent: parent, 181 | modelInitializer: function (elem) { 182 | elem.name = child.name 183 | } 184 | }) 185 | } 186 | 187 | if (child.children) { 188 | child.children.forEach(nextChild => this.createModel(nextParent, nextChild)) 189 | } 190 | } 191 | } 192 | 193 | /** 194 | * Generate 195 | * @param {type.Model} baseModel 196 | * @param {string} basePath 197 | * @param {Object} options 198 | */ 199 | function generate(baseModel, basePath, options) { 200 | var nestCodeGenerator = new NestCodeGenerator(baseModel, basePath) 201 | nestCodeGenerator.generate(baseModel, basePath, options) 202 | } 203 | 204 | exports.generate = generate 205 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | const codeGenerator = require('./lib/code-generator') 2 | const crudGenerator = require('./lib/crud-generator') 3 | const metaGenerator = require('./lib/meta-generator') 4 | 5 | function handleGenerate(base, path, options) { 6 | options = options || getGenOptions() 7 | getBase(base).then(base => { 8 | if (base) { 9 | path = getPath(path) 10 | codeGenerator.generate(base, path, options) 11 | } 12 | }); 13 | } 14 | 15 | function handleGenerateCrud(base, path, options) { 16 | options = options || getGenOptions() 17 | getBase(base).then(base => { 18 | if (base) { 19 | crudGenerator.generate(base, path, options) 20 | } 21 | }); 22 | } 23 | 24 | function handleGenerateMeta(base, path, options) { 25 | options = options || getGenOptions() 26 | getProject(base).then(base => { 27 | if (base) { 28 | metaGenerator.generate(base, path, options) 29 | } 30 | }); 31 | } 32 | 33 | function getGenOptions() { 34 | return { 35 | javaDoc: app.preferences.get('nest.gen.javaDoc'), 36 | useTab: app.preferences.get('nest.gen.useTab'), 37 | indentSpaces: app.preferences.get('nest.gen.indentSpaces'), 38 | tablePrefix: app.preferences.get('nest.gen.tablePrefix') 39 | } 40 | } 41 | 42 | function getBase(base) { 43 | if (!base) { 44 | return app.elementPickerDialog 45 | .showDialog('Select a base model to generate codes', null, type.UMLPackage) 46 | .then(function ({ buttonId, returnValue }) { 47 | if (buttonId === 'ok') { 48 | return returnValue 49 | } 50 | }) 51 | } 52 | return Promise.resolve(base) 53 | } 54 | 55 | function getProject(base) { 56 | if (!base) { 57 | return app.elementPickerDialog 58 | .showDialog('Select a project to generate node_modules', null, type.Project) 59 | .then(function ({ buttonId, returnValue }) { 60 | if (buttonId === 'ok') { 61 | return returnValue 62 | } 63 | }) 64 | } 65 | return Promise.resolve(base) 66 | } 67 | 68 | function getPath(path) { 69 | if (!path) { 70 | var files = app.dialogs.showOpenDialog('Select a folder where generated codes to be located', null, null, { properties: ['openDirectory'] }) 71 | if (files && files.length > 0) { 72 | path = files[0] 73 | } 74 | } 75 | return path 76 | } 77 | 78 | function _handleConfigure() { 79 | app.commands.execute('application:preferences', 'nest') 80 | } 81 | 82 | function init() { 83 | app.commands.register('nest:generate:code', handleGenerate) 84 | app.commands.register('nest:generate:crud', handleGenerateCrud) 85 | app.commands.register('nest:generate:meta', handleGenerateMeta) 86 | app.commands.register('nest:configure', _handleConfigure) 87 | } 88 | 89 | exports.init = init 90 | -------------------------------------------------------------------------------- /menus/menu.json: -------------------------------------------------------------------------------- 1 | { 2 | "menu": [ 3 | { 4 | "id": "tools", 5 | "submenu": [ 6 | { 7 | "label": "NestJS", 8 | "id": "tools.nestjs", 9 | "submenu": [ 10 | { 11 | "label": "Generate Code...", 12 | "id": "tools.nest.generate.code", 13 | "command": "nest:generate:code" 14 | }, 15 | { 16 | "type": "separator" 17 | }, 18 | { 19 | "label": "Add Meta Class...", 20 | "id": "tools.nest.generate.meta", 21 | "command": "nest:generate:meta" 22 | }, 23 | { 24 | "label": "Add Crud Class...", 25 | "id": "tools.nest.generate.crud", 26 | "command": "nest:generate:crud" 27 | }, 28 | { 29 | "type": "separator" 30 | }, 31 | { 32 | "label": "Configure...", 33 | "id": "tools.nest.configure", 34 | "command": "nest:configure" 35 | } 36 | ] 37 | } 38 | ] 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /node_modules/lodash.camelcase/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors 2 | 3 | Based on Underscore.js, copyright Jeremy Ashkenas, 4 | DocumentCloud and Investigative Reporters & Editors 5 | 6 | This software consists of voluntary contributions made by many 7 | individuals. For exact contribution history, see the revision history 8 | available at https://github.com/lodash/lodash 9 | 10 | The following license applies to all parts of this software except as 11 | documented below: 12 | 13 | ==== 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining 16 | a copy of this software and associated documentation files (the 17 | "Software"), to deal in the Software without restriction, including 18 | without limitation the rights to use, copy, modify, merge, publish, 19 | distribute, sublicense, and/or sell copies of the Software, and to 20 | permit persons to whom the Software is furnished to do so, subject to 21 | the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be 24 | included in all copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 | 34 | ==== 35 | 36 | Copyright and related rights for sample code are waived via CC0. Sample 37 | code is defined as all source code displayed within the prose of the 38 | documentation. 39 | 40 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 41 | 42 | ==== 43 | 44 | Files located in the node_modules and vendor directories are externally 45 | maintained libraries used by this software which have their own 46 | licenses; we recommend you read them, as their terms may differ from the 47 | terms above. 48 | -------------------------------------------------------------------------------- /node_modules/lodash.camelcase/README.md: -------------------------------------------------------------------------------- 1 | # lodash.camelcase v4.3.0 2 | 3 | The [lodash](https://lodash.com/) method `_.camelCase` exported as a [Node.js](https://nodejs.org/) module. 4 | 5 | ## Installation 6 | 7 | Using npm: 8 | ```bash 9 | $ {sudo -H} npm i -g npm 10 | $ npm i --save lodash.camelcase 11 | ``` 12 | 13 | In Node.js: 14 | ```js 15 | var camelCase = require('lodash.camelcase'); 16 | ``` 17 | 18 | See the [documentation](https://lodash.com/docs#camelCase) or [package source](https://github.com/lodash/lodash/blob/4.3.0-npm-packages/lodash.camelcase) for more details. 19 | -------------------------------------------------------------------------------- /node_modules/lodash.camelcase/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lodash (Custom Build) 3 | * Build: `lodash modularize exports="npm" -o ./` 4 | * Copyright jQuery Foundation and other contributors 5 | * Released under MIT license 6 | * Based on Underscore.js 1.8.3 7 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 8 | */ 9 | 10 | /** Used as references for various `Number` constants. */ 11 | var INFINITY = 1 / 0; 12 | 13 | /** `Object#toString` result references. */ 14 | var symbolTag = '[object Symbol]'; 15 | 16 | /** Used to match words composed of alphanumeric characters. */ 17 | var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; 18 | 19 | /** Used to match Latin Unicode letters (excluding mathematical operators). */ 20 | var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; 21 | 22 | /** Used to compose unicode character classes. */ 23 | var rsAstralRange = '\\ud800-\\udfff', 24 | rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', 25 | rsComboSymbolsRange = '\\u20d0-\\u20f0', 26 | rsDingbatRange = '\\u2700-\\u27bf', 27 | rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', 28 | rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', 29 | rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', 30 | rsPunctuationRange = '\\u2000-\\u206f', 31 | rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', 32 | rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', 33 | rsVarRange = '\\ufe0e\\ufe0f', 34 | rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; 35 | 36 | /** Used to compose unicode capture groups. */ 37 | var rsApos = "['\u2019]", 38 | rsAstral = '[' + rsAstralRange + ']', 39 | rsBreak = '[' + rsBreakRange + ']', 40 | rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', 41 | rsDigits = '\\d+', 42 | rsDingbat = '[' + rsDingbatRange + ']', 43 | rsLower = '[' + rsLowerRange + ']', 44 | rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', 45 | rsFitz = '\\ud83c[\\udffb-\\udfff]', 46 | rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', 47 | rsNonAstral = '[^' + rsAstralRange + ']', 48 | rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', 49 | rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', 50 | rsUpper = '[' + rsUpperRange + ']', 51 | rsZWJ = '\\u200d'; 52 | 53 | /** Used to compose unicode regexes. */ 54 | var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', 55 | rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', 56 | rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', 57 | rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', 58 | reOptMod = rsModifier + '?', 59 | rsOptVar = '[' + rsVarRange + ']?', 60 | rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', 61 | rsSeq = rsOptVar + reOptMod + rsOptJoin, 62 | rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, 63 | rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; 64 | 65 | /** Used to match apostrophes. */ 66 | var reApos = RegExp(rsApos, 'g'); 67 | 68 | /** 69 | * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and 70 | * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). 71 | */ 72 | var reComboMark = RegExp(rsCombo, 'g'); 73 | 74 | /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ 75 | var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); 76 | 77 | /** Used to match complex or compound words. */ 78 | var reUnicodeWord = RegExp([ 79 | rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', 80 | rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', 81 | rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, 82 | rsUpper + '+' + rsOptUpperContr, 83 | rsDigits, 84 | rsEmoji 85 | ].join('|'), 'g'); 86 | 87 | /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ 88 | var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); 89 | 90 | /** Used to detect strings that need a more robust regexp to match words. */ 91 | var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; 92 | 93 | /** Used to map Latin Unicode letters to basic Latin letters. */ 94 | var deburredLetters = { 95 | // Latin-1 Supplement block. 96 | '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', 97 | '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', 98 | '\xc7': 'C', '\xe7': 'c', 99 | '\xd0': 'D', '\xf0': 'd', 100 | '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', 101 | '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', 102 | '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', 103 | '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', 104 | '\xd1': 'N', '\xf1': 'n', 105 | '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', 106 | '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', 107 | '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', 108 | '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', 109 | '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', 110 | '\xc6': 'Ae', '\xe6': 'ae', 111 | '\xde': 'Th', '\xfe': 'th', 112 | '\xdf': 'ss', 113 | // Latin Extended-A block. 114 | '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', 115 | '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', 116 | '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', 117 | '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', 118 | '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', 119 | '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', 120 | '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', 121 | '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', 122 | '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', 123 | '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', 124 | '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', 125 | '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', 126 | '\u0134': 'J', '\u0135': 'j', 127 | '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', 128 | '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', 129 | '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', 130 | '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', 131 | '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', 132 | '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', 133 | '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', 134 | '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', 135 | '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', 136 | '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', 137 | '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', 138 | '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', 139 | '\u0163': 't', '\u0165': 't', '\u0167': 't', 140 | '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', 141 | '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', 142 | '\u0174': 'W', '\u0175': 'w', 143 | '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', 144 | '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', 145 | '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', 146 | '\u0132': 'IJ', '\u0133': 'ij', 147 | '\u0152': 'Oe', '\u0153': 'oe', 148 | '\u0149': "'n", '\u017f': 'ss' 149 | }; 150 | 151 | /** Detect free variable `global` from Node.js. */ 152 | var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; 153 | 154 | /** Detect free variable `self`. */ 155 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self; 156 | 157 | /** Used as a reference to the global object. */ 158 | var root = freeGlobal || freeSelf || Function('return this')(); 159 | 160 | /** 161 | * A specialized version of `_.reduce` for arrays without support for 162 | * iteratee shorthands. 163 | * 164 | * @private 165 | * @param {Array} [array] The array to iterate over. 166 | * @param {Function} iteratee The function invoked per iteration. 167 | * @param {*} [accumulator] The initial value. 168 | * @param {boolean} [initAccum] Specify using the first element of `array` as 169 | * the initial value. 170 | * @returns {*} Returns the accumulated value. 171 | */ 172 | function arrayReduce(array, iteratee, accumulator, initAccum) { 173 | var index = -1, 174 | length = array ? array.length : 0; 175 | 176 | if (initAccum && length) { 177 | accumulator = array[++index]; 178 | } 179 | while (++index < length) { 180 | accumulator = iteratee(accumulator, array[index], index, array); 181 | } 182 | return accumulator; 183 | } 184 | 185 | /** 186 | * Converts an ASCII `string` to an array. 187 | * 188 | * @private 189 | * @param {string} string The string to convert. 190 | * @returns {Array} Returns the converted array. 191 | */ 192 | function asciiToArray(string) { 193 | return string.split(''); 194 | } 195 | 196 | /** 197 | * Splits an ASCII `string` into an array of its words. 198 | * 199 | * @private 200 | * @param {string} The string to inspect. 201 | * @returns {Array} Returns the words of `string`. 202 | */ 203 | function asciiWords(string) { 204 | return string.match(reAsciiWord) || []; 205 | } 206 | 207 | /** 208 | * The base implementation of `_.propertyOf` without support for deep paths. 209 | * 210 | * @private 211 | * @param {Object} object The object to query. 212 | * @returns {Function} Returns the new accessor function. 213 | */ 214 | function basePropertyOf(object) { 215 | return function(key) { 216 | return object == null ? undefined : object[key]; 217 | }; 218 | } 219 | 220 | /** 221 | * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A 222 | * letters to basic Latin letters. 223 | * 224 | * @private 225 | * @param {string} letter The matched letter to deburr. 226 | * @returns {string} Returns the deburred letter. 227 | */ 228 | var deburrLetter = basePropertyOf(deburredLetters); 229 | 230 | /** 231 | * Checks if `string` contains Unicode symbols. 232 | * 233 | * @private 234 | * @param {string} string The string to inspect. 235 | * @returns {boolean} Returns `true` if a symbol is found, else `false`. 236 | */ 237 | function hasUnicode(string) { 238 | return reHasUnicode.test(string); 239 | } 240 | 241 | /** 242 | * Checks if `string` contains a word composed of Unicode symbols. 243 | * 244 | * @private 245 | * @param {string} string The string to inspect. 246 | * @returns {boolean} Returns `true` if a word is found, else `false`. 247 | */ 248 | function hasUnicodeWord(string) { 249 | return reHasUnicodeWord.test(string); 250 | } 251 | 252 | /** 253 | * Converts `string` to an array. 254 | * 255 | * @private 256 | * @param {string} string The string to convert. 257 | * @returns {Array} Returns the converted array. 258 | */ 259 | function stringToArray(string) { 260 | return hasUnicode(string) 261 | ? unicodeToArray(string) 262 | : asciiToArray(string); 263 | } 264 | 265 | /** 266 | * Converts a Unicode `string` to an array. 267 | * 268 | * @private 269 | * @param {string} string The string to convert. 270 | * @returns {Array} Returns the converted array. 271 | */ 272 | function unicodeToArray(string) { 273 | return string.match(reUnicode) || []; 274 | } 275 | 276 | /** 277 | * Splits a Unicode `string` into an array of its words. 278 | * 279 | * @private 280 | * @param {string} The string to inspect. 281 | * @returns {Array} Returns the words of `string`. 282 | */ 283 | function unicodeWords(string) { 284 | return string.match(reUnicodeWord) || []; 285 | } 286 | 287 | /** Used for built-in method references. */ 288 | var objectProto = Object.prototype; 289 | 290 | /** 291 | * Used to resolve the 292 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) 293 | * of values. 294 | */ 295 | var objectToString = objectProto.toString; 296 | 297 | /** Built-in value references. */ 298 | var Symbol = root.Symbol; 299 | 300 | /** Used to convert symbols to primitives and strings. */ 301 | var symbolProto = Symbol ? Symbol.prototype : undefined, 302 | symbolToString = symbolProto ? symbolProto.toString : undefined; 303 | 304 | /** 305 | * The base implementation of `_.slice` without an iteratee call guard. 306 | * 307 | * @private 308 | * @param {Array} array The array to slice. 309 | * @param {number} [start=0] The start position. 310 | * @param {number} [end=array.length] The end position. 311 | * @returns {Array} Returns the slice of `array`. 312 | */ 313 | function baseSlice(array, start, end) { 314 | var index = -1, 315 | length = array.length; 316 | 317 | if (start < 0) { 318 | start = -start > length ? 0 : (length + start); 319 | } 320 | end = end > length ? length : end; 321 | if (end < 0) { 322 | end += length; 323 | } 324 | length = start > end ? 0 : ((end - start) >>> 0); 325 | start >>>= 0; 326 | 327 | var result = Array(length); 328 | while (++index < length) { 329 | result[index] = array[index + start]; 330 | } 331 | return result; 332 | } 333 | 334 | /** 335 | * The base implementation of `_.toString` which doesn't convert nullish 336 | * values to empty strings. 337 | * 338 | * @private 339 | * @param {*} value The value to process. 340 | * @returns {string} Returns the string. 341 | */ 342 | function baseToString(value) { 343 | // Exit early for strings to avoid a performance hit in some environments. 344 | if (typeof value == 'string') { 345 | return value; 346 | } 347 | if (isSymbol(value)) { 348 | return symbolToString ? symbolToString.call(value) : ''; 349 | } 350 | var result = (value + ''); 351 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; 352 | } 353 | 354 | /** 355 | * Casts `array` to a slice if it's needed. 356 | * 357 | * @private 358 | * @param {Array} array The array to inspect. 359 | * @param {number} start The start position. 360 | * @param {number} [end=array.length] The end position. 361 | * @returns {Array} Returns the cast slice. 362 | */ 363 | function castSlice(array, start, end) { 364 | var length = array.length; 365 | end = end === undefined ? length : end; 366 | return (!start && end >= length) ? array : baseSlice(array, start, end); 367 | } 368 | 369 | /** 370 | * Creates a function like `_.lowerFirst`. 371 | * 372 | * @private 373 | * @param {string} methodName The name of the `String` case method to use. 374 | * @returns {Function} Returns the new case function. 375 | */ 376 | function createCaseFirst(methodName) { 377 | return function(string) { 378 | string = toString(string); 379 | 380 | var strSymbols = hasUnicode(string) 381 | ? stringToArray(string) 382 | : undefined; 383 | 384 | var chr = strSymbols 385 | ? strSymbols[0] 386 | : string.charAt(0); 387 | 388 | var trailing = strSymbols 389 | ? castSlice(strSymbols, 1).join('') 390 | : string.slice(1); 391 | 392 | return chr[methodName]() + trailing; 393 | }; 394 | } 395 | 396 | /** 397 | * Creates a function like `_.camelCase`. 398 | * 399 | * @private 400 | * @param {Function} callback The function to combine each word. 401 | * @returns {Function} Returns the new compounder function. 402 | */ 403 | function createCompounder(callback) { 404 | return function(string) { 405 | return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); 406 | }; 407 | } 408 | 409 | /** 410 | * Checks if `value` is object-like. A value is object-like if it's not `null` 411 | * and has a `typeof` result of "object". 412 | * 413 | * @static 414 | * @memberOf _ 415 | * @since 4.0.0 416 | * @category Lang 417 | * @param {*} value The value to check. 418 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`. 419 | * @example 420 | * 421 | * _.isObjectLike({}); 422 | * // => true 423 | * 424 | * _.isObjectLike([1, 2, 3]); 425 | * // => true 426 | * 427 | * _.isObjectLike(_.noop); 428 | * // => false 429 | * 430 | * _.isObjectLike(null); 431 | * // => false 432 | */ 433 | function isObjectLike(value) { 434 | return !!value && typeof value == 'object'; 435 | } 436 | 437 | /** 438 | * Checks if `value` is classified as a `Symbol` primitive or object. 439 | * 440 | * @static 441 | * @memberOf _ 442 | * @since 4.0.0 443 | * @category Lang 444 | * @param {*} value The value to check. 445 | * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. 446 | * @example 447 | * 448 | * _.isSymbol(Symbol.iterator); 449 | * // => true 450 | * 451 | * _.isSymbol('abc'); 452 | * // => false 453 | */ 454 | function isSymbol(value) { 455 | return typeof value == 'symbol' || 456 | (isObjectLike(value) && objectToString.call(value) == symbolTag); 457 | } 458 | 459 | /** 460 | * Converts `value` to a string. An empty string is returned for `null` 461 | * and `undefined` values. The sign of `-0` is preserved. 462 | * 463 | * @static 464 | * @memberOf _ 465 | * @since 4.0.0 466 | * @category Lang 467 | * @param {*} value The value to process. 468 | * @returns {string} Returns the string. 469 | * @example 470 | * 471 | * _.toString(null); 472 | * // => '' 473 | * 474 | * _.toString(-0); 475 | * // => '-0' 476 | * 477 | * _.toString([1, 2, 3]); 478 | * // => '1,2,3' 479 | */ 480 | function toString(value) { 481 | return value == null ? '' : baseToString(value); 482 | } 483 | 484 | /** 485 | * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). 486 | * 487 | * @static 488 | * @memberOf _ 489 | * @since 3.0.0 490 | * @category String 491 | * @param {string} [string=''] The string to convert. 492 | * @returns {string} Returns the camel cased string. 493 | * @example 494 | * 495 | * _.camelCase('Foo Bar'); 496 | * // => 'fooBar' 497 | * 498 | * _.camelCase('--foo-bar--'); 499 | * // => 'fooBar' 500 | * 501 | * _.camelCase('__FOO_BAR__'); 502 | * // => 'fooBar' 503 | */ 504 | var camelCase = createCompounder(function(result, word, index) { 505 | word = word.toLowerCase(); 506 | return result + (index ? capitalize(word) : word); 507 | }); 508 | 509 | /** 510 | * Converts the first character of `string` to upper case and the remaining 511 | * to lower case. 512 | * 513 | * @static 514 | * @memberOf _ 515 | * @since 3.0.0 516 | * @category String 517 | * @param {string} [string=''] The string to capitalize. 518 | * @returns {string} Returns the capitalized string. 519 | * @example 520 | * 521 | * _.capitalize('FRED'); 522 | * // => 'Fred' 523 | */ 524 | function capitalize(string) { 525 | return upperFirst(toString(string).toLowerCase()); 526 | } 527 | 528 | /** 529 | * Deburrs `string` by converting 530 | * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) 531 | * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) 532 | * letters to basic Latin letters and removing 533 | * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). 534 | * 535 | * @static 536 | * @memberOf _ 537 | * @since 3.0.0 538 | * @category String 539 | * @param {string} [string=''] The string to deburr. 540 | * @returns {string} Returns the deburred string. 541 | * @example 542 | * 543 | * _.deburr('déjà vu'); 544 | * // => 'deja vu' 545 | */ 546 | function deburr(string) { 547 | string = toString(string); 548 | return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); 549 | } 550 | 551 | /** 552 | * Converts the first character of `string` to upper case. 553 | * 554 | * @static 555 | * @memberOf _ 556 | * @since 4.0.0 557 | * @category String 558 | * @param {string} [string=''] The string to convert. 559 | * @returns {string} Returns the converted string. 560 | * @example 561 | * 562 | * _.upperFirst('fred'); 563 | * // => 'Fred' 564 | * 565 | * _.upperFirst('FRED'); 566 | * // => 'FRED' 567 | */ 568 | var upperFirst = createCaseFirst('toUpperCase'); 569 | 570 | /** 571 | * Splits `string` into an array of its words. 572 | * 573 | * @static 574 | * @memberOf _ 575 | * @since 3.0.0 576 | * @category String 577 | * @param {string} [string=''] The string to inspect. 578 | * @param {RegExp|string} [pattern] The pattern to match words. 579 | * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 580 | * @returns {Array} Returns the words of `string`. 581 | * @example 582 | * 583 | * _.words('fred, barney, & pebbles'); 584 | * // => ['fred', 'barney', 'pebbles'] 585 | * 586 | * _.words('fred, barney, & pebbles', /[^, ]+/g); 587 | * // => ['fred', 'barney', '&', 'pebbles'] 588 | */ 589 | function words(string, pattern, guard) { 590 | string = toString(string); 591 | pattern = guard ? undefined : pattern; 592 | 593 | if (pattern === undefined) { 594 | return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); 595 | } 596 | return string.match(pattern) || []; 597 | } 598 | 599 | module.exports = camelCase; 600 | -------------------------------------------------------------------------------- /node_modules/lodash.camelcase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "lodash.camelcase", 3 | "_id": "lodash.camelcase@4.3.0", 4 | "_inBundle": false, 5 | "_integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", 6 | "_location": "/lodash.camelcase", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "lodash.camelcase", 12 | "name": "lodash.camelcase", 13 | "escapedName": "lodash.camelcase", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 23 | "_shasum": "b28aa6288a2b9fc651035c7711f65ab6190331a6", 24 | "_spec": "lodash.camelcase", 25 | "_where": "/Users/jeff/Library/Application Support/StarUML/extensions/user/staruml-nestjs", 26 | "author": { 27 | "name": "John-David Dalton", 28 | "email": "john.david.dalton@gmail.com", 29 | "url": "http://allyoucanleet.com/" 30 | }, 31 | "bugs": { 32 | "url": "https://github.com/lodash/lodash/issues" 33 | }, 34 | "bundleDependencies": false, 35 | "contributors": [ 36 | { 37 | "name": "John-David Dalton", 38 | "email": "john.david.dalton@gmail.com", 39 | "url": "http://allyoucanleet.com/" 40 | }, 41 | { 42 | "name": "Blaine Bublitz", 43 | "email": "blaine.bublitz@gmail.com", 44 | "url": "https://github.com/phated" 45 | }, 46 | { 47 | "name": "Mathias Bynens", 48 | "email": "mathias@qiwi.be", 49 | "url": "https://mathiasbynens.be/" 50 | } 51 | ], 52 | "deprecated": false, 53 | "description": "The lodash method `_.camelCase` exported as a module.", 54 | "homepage": "https://lodash.com/", 55 | "icon": "https://lodash.com/icon.svg", 56 | "keywords": [ 57 | "lodash-modularized", 58 | "camelcase" 59 | ], 60 | "license": "MIT", 61 | "name": "lodash.camelcase", 62 | "repository": { 63 | "type": "git", 64 | "url": "git+https://github.com/lodash/lodash.git" 65 | }, 66 | "scripts": { 67 | "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" 68 | }, 69 | "version": "4.3.0" 70 | } 71 | -------------------------------------------------------------------------------- /node_modules/lodash.capitalize/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors 2 | 3 | Based on Underscore.js, copyright Jeremy Ashkenas, 4 | DocumentCloud and Investigative Reporters & Editors 5 | 6 | This software consists of voluntary contributions made by many 7 | individuals. For exact contribution history, see the revision history 8 | available at https://github.com/lodash/lodash 9 | 10 | The following license applies to all parts of this software except as 11 | documented below: 12 | 13 | ==== 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining 16 | a copy of this software and associated documentation files (the 17 | "Software"), to deal in the Software without restriction, including 18 | without limitation the rights to use, copy, modify, merge, publish, 19 | distribute, sublicense, and/or sell copies of the Software, and to 20 | permit persons to whom the Software is furnished to do so, subject to 21 | the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be 24 | included in all copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 | 34 | ==== 35 | 36 | Copyright and related rights for sample code are waived via CC0. Sample 37 | code is defined as all source code displayed within the prose of the 38 | documentation. 39 | 40 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 41 | 42 | ==== 43 | 44 | Files located in the node_modules and vendor directories are externally 45 | maintained libraries used by this software which have their own 46 | licenses; we recommend you read them, as their terms may differ from the 47 | terms above. 48 | -------------------------------------------------------------------------------- /node_modules/lodash.capitalize/README.md: -------------------------------------------------------------------------------- 1 | # lodash.capitalize v4.2.1 2 | 3 | The [lodash](https://lodash.com/) method `_.capitalize` exported as a [Node.js](https://nodejs.org/) module. 4 | 5 | ## Installation 6 | 7 | Using npm: 8 | ```bash 9 | $ {sudo -H} npm i -g npm 10 | $ npm i --save lodash.capitalize 11 | ``` 12 | 13 | In Node.js: 14 | ```js 15 | var capitalize = require('lodash.capitalize'); 16 | ``` 17 | 18 | See the [documentation](https://lodash.com/docs#capitalize) or [package source](https://github.com/lodash/lodash/blob/4.2.1-npm-packages/lodash.capitalize) for more details. 19 | -------------------------------------------------------------------------------- /node_modules/lodash.capitalize/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lodash (Custom Build) 3 | * Build: `lodash modularize exports="npm" -o ./` 4 | * Copyright jQuery Foundation and other contributors 5 | * Released under MIT license 6 | * Based on Underscore.js 1.8.3 7 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 8 | */ 9 | 10 | /** Used as references for various `Number` constants. */ 11 | var INFINITY = 1 / 0; 12 | 13 | /** `Object#toString` result references. */ 14 | var symbolTag = '[object Symbol]'; 15 | 16 | /** Used to compose unicode character classes. */ 17 | var rsAstralRange = '\\ud800-\\udfff', 18 | rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', 19 | rsComboSymbolsRange = '\\u20d0-\\u20f0', 20 | rsVarRange = '\\ufe0e\\ufe0f'; 21 | 22 | /** Used to compose unicode capture groups. */ 23 | var rsAstral = '[' + rsAstralRange + ']', 24 | rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', 25 | rsFitz = '\\ud83c[\\udffb-\\udfff]', 26 | rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', 27 | rsNonAstral = '[^' + rsAstralRange + ']', 28 | rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', 29 | rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', 30 | rsZWJ = '\\u200d'; 31 | 32 | /** Used to compose unicode regexes. */ 33 | var reOptMod = rsModifier + '?', 34 | rsOptVar = '[' + rsVarRange + ']?', 35 | rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', 36 | rsSeq = rsOptVar + reOptMod + rsOptJoin, 37 | rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; 38 | 39 | /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ 40 | var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); 41 | 42 | /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ 43 | var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); 44 | 45 | /** Detect free variable `global` from Node.js. */ 46 | var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; 47 | 48 | /** Detect free variable `self`. */ 49 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self; 50 | 51 | /** Used as a reference to the global object. */ 52 | var root = freeGlobal || freeSelf || Function('return this')(); 53 | 54 | /** 55 | * Converts an ASCII `string` to an array. 56 | * 57 | * @private 58 | * @param {string} string The string to convert. 59 | * @returns {Array} Returns the converted array. 60 | */ 61 | function asciiToArray(string) { 62 | return string.split(''); 63 | } 64 | 65 | /** 66 | * Checks if `string` contains Unicode symbols. 67 | * 68 | * @private 69 | * @param {string} string The string to inspect. 70 | * @returns {boolean} Returns `true` if a symbol is found, else `false`. 71 | */ 72 | function hasUnicode(string) { 73 | return reHasUnicode.test(string); 74 | } 75 | 76 | /** 77 | * Converts `string` to an array. 78 | * 79 | * @private 80 | * @param {string} string The string to convert. 81 | * @returns {Array} Returns the converted array. 82 | */ 83 | function stringToArray(string) { 84 | return hasUnicode(string) 85 | ? unicodeToArray(string) 86 | : asciiToArray(string); 87 | } 88 | 89 | /** 90 | * Converts a Unicode `string` to an array. 91 | * 92 | * @private 93 | * @param {string} string The string to convert. 94 | * @returns {Array} Returns the converted array. 95 | */ 96 | function unicodeToArray(string) { 97 | return string.match(reUnicode) || []; 98 | } 99 | 100 | /** Used for built-in method references. */ 101 | var objectProto = Object.prototype; 102 | 103 | /** 104 | * Used to resolve the 105 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) 106 | * of values. 107 | */ 108 | var objectToString = objectProto.toString; 109 | 110 | /** Built-in value references. */ 111 | var Symbol = root.Symbol; 112 | 113 | /** Used to convert symbols to primitives and strings. */ 114 | var symbolProto = Symbol ? Symbol.prototype : undefined, 115 | symbolToString = symbolProto ? symbolProto.toString : undefined; 116 | 117 | /** 118 | * The base implementation of `_.slice` without an iteratee call guard. 119 | * 120 | * @private 121 | * @param {Array} array The array to slice. 122 | * @param {number} [start=0] The start position. 123 | * @param {number} [end=array.length] The end position. 124 | * @returns {Array} Returns the slice of `array`. 125 | */ 126 | function baseSlice(array, start, end) { 127 | var index = -1, 128 | length = array.length; 129 | 130 | if (start < 0) { 131 | start = -start > length ? 0 : (length + start); 132 | } 133 | end = end > length ? length : end; 134 | if (end < 0) { 135 | end += length; 136 | } 137 | length = start > end ? 0 : ((end - start) >>> 0); 138 | start >>>= 0; 139 | 140 | var result = Array(length); 141 | while (++index < length) { 142 | result[index] = array[index + start]; 143 | } 144 | return result; 145 | } 146 | 147 | /** 148 | * The base implementation of `_.toString` which doesn't convert nullish 149 | * values to empty strings. 150 | * 151 | * @private 152 | * @param {*} value The value to process. 153 | * @returns {string} Returns the string. 154 | */ 155 | function baseToString(value) { 156 | // Exit early for strings to avoid a performance hit in some environments. 157 | if (typeof value == 'string') { 158 | return value; 159 | } 160 | if (isSymbol(value)) { 161 | return symbolToString ? symbolToString.call(value) : ''; 162 | } 163 | var result = (value + ''); 164 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; 165 | } 166 | 167 | /** 168 | * Casts `array` to a slice if it's needed. 169 | * 170 | * @private 171 | * @param {Array} array The array to inspect. 172 | * @param {number} start The start position. 173 | * @param {number} [end=array.length] The end position. 174 | * @returns {Array} Returns the cast slice. 175 | */ 176 | function castSlice(array, start, end) { 177 | var length = array.length; 178 | end = end === undefined ? length : end; 179 | return (!start && end >= length) ? array : baseSlice(array, start, end); 180 | } 181 | 182 | /** 183 | * Creates a function like `_.lowerFirst`. 184 | * 185 | * @private 186 | * @param {string} methodName The name of the `String` case method to use. 187 | * @returns {Function} Returns the new case function. 188 | */ 189 | function createCaseFirst(methodName) { 190 | return function(string) { 191 | string = toString(string); 192 | 193 | var strSymbols = hasUnicode(string) 194 | ? stringToArray(string) 195 | : undefined; 196 | 197 | var chr = strSymbols 198 | ? strSymbols[0] 199 | : string.charAt(0); 200 | 201 | var trailing = strSymbols 202 | ? castSlice(strSymbols, 1).join('') 203 | : string.slice(1); 204 | 205 | return chr[methodName]() + trailing; 206 | }; 207 | } 208 | 209 | /** 210 | * Checks if `value` is object-like. A value is object-like if it's not `null` 211 | * and has a `typeof` result of "object". 212 | * 213 | * @static 214 | * @memberOf _ 215 | * @since 4.0.0 216 | * @category Lang 217 | * @param {*} value The value to check. 218 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`. 219 | * @example 220 | * 221 | * _.isObjectLike({}); 222 | * // => true 223 | * 224 | * _.isObjectLike([1, 2, 3]); 225 | * // => true 226 | * 227 | * _.isObjectLike(_.noop); 228 | * // => false 229 | * 230 | * _.isObjectLike(null); 231 | * // => false 232 | */ 233 | function isObjectLike(value) { 234 | return !!value && typeof value == 'object'; 235 | } 236 | 237 | /** 238 | * Checks if `value` is classified as a `Symbol` primitive or object. 239 | * 240 | * @static 241 | * @memberOf _ 242 | * @since 4.0.0 243 | * @category Lang 244 | * @param {*} value The value to check. 245 | * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. 246 | * @example 247 | * 248 | * _.isSymbol(Symbol.iterator); 249 | * // => true 250 | * 251 | * _.isSymbol('abc'); 252 | * // => false 253 | */ 254 | function isSymbol(value) { 255 | return typeof value == 'symbol' || 256 | (isObjectLike(value) && objectToString.call(value) == symbolTag); 257 | } 258 | 259 | /** 260 | * Converts `value` to a string. An empty string is returned for `null` 261 | * and `undefined` values. The sign of `-0` is preserved. 262 | * 263 | * @static 264 | * @memberOf _ 265 | * @since 4.0.0 266 | * @category Lang 267 | * @param {*} value The value to process. 268 | * @returns {string} Returns the string. 269 | * @example 270 | * 271 | * _.toString(null); 272 | * // => '' 273 | * 274 | * _.toString(-0); 275 | * // => '-0' 276 | * 277 | * _.toString([1, 2, 3]); 278 | * // => '1,2,3' 279 | */ 280 | function toString(value) { 281 | return value == null ? '' : baseToString(value); 282 | } 283 | 284 | /** 285 | * Converts the first character of `string` to upper case and the remaining 286 | * to lower case. 287 | * 288 | * @static 289 | * @memberOf _ 290 | * @since 3.0.0 291 | * @category String 292 | * @param {string} [string=''] The string to capitalize. 293 | * @returns {string} Returns the capitalized string. 294 | * @example 295 | * 296 | * _.capitalize('FRED'); 297 | * // => 'Fred' 298 | */ 299 | function capitalize(string) { 300 | return upperFirst(toString(string).toLowerCase()); 301 | } 302 | 303 | /** 304 | * Converts the first character of `string` to upper case. 305 | * 306 | * @static 307 | * @memberOf _ 308 | * @since 4.0.0 309 | * @category String 310 | * @param {string} [string=''] The string to convert. 311 | * @returns {string} Returns the converted string. 312 | * @example 313 | * 314 | * _.upperFirst('fred'); 315 | * // => 'Fred' 316 | * 317 | * _.upperFirst('FRED'); 318 | * // => 'FRED' 319 | */ 320 | var upperFirst = createCaseFirst('toUpperCase'); 321 | 322 | module.exports = capitalize; 323 | -------------------------------------------------------------------------------- /node_modules/lodash.capitalize/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "lodash.capitalize", 3 | "_id": "lodash.capitalize@4.2.1", 4 | "_inBundle": false, 5 | "_integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=", 6 | "_location": "/lodash.capitalize", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "lodash.capitalize", 12 | "name": "lodash.capitalize", 13 | "escapedName": "lodash.capitalize", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", 23 | "_shasum": "f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9", 24 | "_spec": "lodash.capitalize", 25 | "_where": "/Users/jeff/Library/Application Support/StarUML/extensions/user/staruml-nestjs", 26 | "author": { 27 | "name": "John-David Dalton", 28 | "email": "john.david.dalton@gmail.com", 29 | "url": "http://allyoucanleet.com/" 30 | }, 31 | "bugs": { 32 | "url": "https://github.com/lodash/lodash/issues" 33 | }, 34 | "bundleDependencies": false, 35 | "contributors": [ 36 | { 37 | "name": "John-David Dalton", 38 | "email": "john.david.dalton@gmail.com", 39 | "url": "http://allyoucanleet.com/" 40 | }, 41 | { 42 | "name": "Blaine Bublitz", 43 | "email": "blaine.bublitz@gmail.com", 44 | "url": "https://github.com/phated" 45 | }, 46 | { 47 | "name": "Mathias Bynens", 48 | "email": "mathias@qiwi.be", 49 | "url": "https://mathiasbynens.be/" 50 | } 51 | ], 52 | "deprecated": false, 53 | "description": "The lodash method `_.capitalize` exported as a module.", 54 | "homepage": "https://lodash.com/", 55 | "icon": "https://lodash.com/icon.svg", 56 | "keywords": [ 57 | "lodash-modularized", 58 | "capitalize" 59 | ], 60 | "license": "MIT", 61 | "name": "lodash.capitalize", 62 | "repository": { 63 | "type": "git", 64 | "url": "git+https://github.com/lodash/lodash.git" 65 | }, 66 | "scripts": { 67 | "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" 68 | }, 69 | "version": "4.2.1" 70 | } 71 | -------------------------------------------------------------------------------- /node_modules/lodash.kebabcase/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors 2 | 3 | Based on Underscore.js, copyright Jeremy Ashkenas, 4 | DocumentCloud and Investigative Reporters & Editors 5 | 6 | This software consists of voluntary contributions made by many 7 | individuals. For exact contribution history, see the revision history 8 | available at https://github.com/lodash/lodash 9 | 10 | The following license applies to all parts of this software except as 11 | documented below: 12 | 13 | ==== 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining 16 | a copy of this software and associated documentation files (the 17 | "Software"), to deal in the Software without restriction, including 18 | without limitation the rights to use, copy, modify, merge, publish, 19 | distribute, sublicense, and/or sell copies of the Software, and to 20 | permit persons to whom the Software is furnished to do so, subject to 21 | the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be 24 | included in all copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 | 34 | ==== 35 | 36 | Copyright and related rights for sample code are waived via CC0. Sample 37 | code is defined as all source code displayed within the prose of the 38 | documentation. 39 | 40 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 41 | 42 | ==== 43 | 44 | Files located in the node_modules and vendor directories are externally 45 | maintained libraries used by this software which have their own 46 | licenses; we recommend you read them, as their terms may differ from the 47 | terms above. 48 | -------------------------------------------------------------------------------- /node_modules/lodash.kebabcase/README.md: -------------------------------------------------------------------------------- 1 | # lodash.kebabcase v4.1.1 2 | 3 | The [lodash](https://lodash.com/) method `_.kebabCase` exported as a [Node.js](https://nodejs.org/) module. 4 | 5 | ## Installation 6 | 7 | Using npm: 8 | ```bash 9 | $ {sudo -H} npm i -g npm 10 | $ npm i --save lodash.kebabcase 11 | ``` 12 | 13 | In Node.js: 14 | ```js 15 | var kebabCase = require('lodash.kebabcase'); 16 | ``` 17 | 18 | See the [documentation](https://lodash.com/docs#kebabCase) or [package source](https://github.com/lodash/lodash/blob/4.1.1-npm-packages/lodash.kebabcase) for more details. 19 | -------------------------------------------------------------------------------- /node_modules/lodash.kebabcase/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lodash (Custom Build) 3 | * Build: `lodash modularize exports="npm" -o ./` 4 | * Copyright jQuery Foundation and other contributors 5 | * Released under MIT license 6 | * Based on Underscore.js 1.8.3 7 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 8 | */ 9 | 10 | /** Used as references for various `Number` constants. */ 11 | var INFINITY = 1 / 0; 12 | 13 | /** `Object#toString` result references. */ 14 | var symbolTag = '[object Symbol]'; 15 | 16 | /** Used to match words composed of alphanumeric characters. */ 17 | var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; 18 | 19 | /** Used to match Latin Unicode letters (excluding mathematical operators). */ 20 | var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; 21 | 22 | /** Used to compose unicode character classes. */ 23 | var rsAstralRange = '\\ud800-\\udfff', 24 | rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', 25 | rsComboSymbolsRange = '\\u20d0-\\u20f0', 26 | rsDingbatRange = '\\u2700-\\u27bf', 27 | rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', 28 | rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', 29 | rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', 30 | rsPunctuationRange = '\\u2000-\\u206f', 31 | rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', 32 | rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', 33 | rsVarRange = '\\ufe0e\\ufe0f', 34 | rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; 35 | 36 | /** Used to compose unicode capture groups. */ 37 | var rsApos = "['\u2019]", 38 | rsBreak = '[' + rsBreakRange + ']', 39 | rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', 40 | rsDigits = '\\d+', 41 | rsDingbat = '[' + rsDingbatRange + ']', 42 | rsLower = '[' + rsLowerRange + ']', 43 | rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', 44 | rsFitz = '\\ud83c[\\udffb-\\udfff]', 45 | rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', 46 | rsNonAstral = '[^' + rsAstralRange + ']', 47 | rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', 48 | rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', 49 | rsUpper = '[' + rsUpperRange + ']', 50 | rsZWJ = '\\u200d'; 51 | 52 | /** Used to compose unicode regexes. */ 53 | var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', 54 | rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', 55 | rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', 56 | rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', 57 | reOptMod = rsModifier + '?', 58 | rsOptVar = '[' + rsVarRange + ']?', 59 | rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', 60 | rsSeq = rsOptVar + reOptMod + rsOptJoin, 61 | rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq; 62 | 63 | /** Used to match apostrophes. */ 64 | var reApos = RegExp(rsApos, 'g'); 65 | 66 | /** 67 | * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and 68 | * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). 69 | */ 70 | var reComboMark = RegExp(rsCombo, 'g'); 71 | 72 | /** Used to match complex or compound words. */ 73 | var reUnicodeWord = RegExp([ 74 | rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', 75 | rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', 76 | rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, 77 | rsUpper + '+' + rsOptUpperContr, 78 | rsDigits, 79 | rsEmoji 80 | ].join('|'), 'g'); 81 | 82 | /** Used to detect strings that need a more robust regexp to match words. */ 83 | var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; 84 | 85 | /** Used to map Latin Unicode letters to basic Latin letters. */ 86 | var deburredLetters = { 87 | // Latin-1 Supplement block. 88 | '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', 89 | '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', 90 | '\xc7': 'C', '\xe7': 'c', 91 | '\xd0': 'D', '\xf0': 'd', 92 | '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', 93 | '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', 94 | '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', 95 | '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', 96 | '\xd1': 'N', '\xf1': 'n', 97 | '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', 98 | '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', 99 | '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', 100 | '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', 101 | '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', 102 | '\xc6': 'Ae', '\xe6': 'ae', 103 | '\xde': 'Th', '\xfe': 'th', 104 | '\xdf': 'ss', 105 | // Latin Extended-A block. 106 | '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', 107 | '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', 108 | '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', 109 | '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', 110 | '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', 111 | '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', 112 | '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', 113 | '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', 114 | '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', 115 | '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', 116 | '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', 117 | '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', 118 | '\u0134': 'J', '\u0135': 'j', 119 | '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', 120 | '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', 121 | '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', 122 | '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', 123 | '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', 124 | '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', 125 | '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', 126 | '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', 127 | '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', 128 | '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', 129 | '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', 130 | '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', 131 | '\u0163': 't', '\u0165': 't', '\u0167': 't', 132 | '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', 133 | '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', 134 | '\u0174': 'W', '\u0175': 'w', 135 | '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', 136 | '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', 137 | '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', 138 | '\u0132': 'IJ', '\u0133': 'ij', 139 | '\u0152': 'Oe', '\u0153': 'oe', 140 | '\u0149': "'n", '\u017f': 'ss' 141 | }; 142 | 143 | /** Detect free variable `global` from Node.js. */ 144 | var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; 145 | 146 | /** Detect free variable `self`. */ 147 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self; 148 | 149 | /** Used as a reference to the global object. */ 150 | var root = freeGlobal || freeSelf || Function('return this')(); 151 | 152 | /** 153 | * A specialized version of `_.reduce` for arrays without support for 154 | * iteratee shorthands. 155 | * 156 | * @private 157 | * @param {Array} [array] The array to iterate over. 158 | * @param {Function} iteratee The function invoked per iteration. 159 | * @param {*} [accumulator] The initial value. 160 | * @param {boolean} [initAccum] Specify using the first element of `array` as 161 | * the initial value. 162 | * @returns {*} Returns the accumulated value. 163 | */ 164 | function arrayReduce(array, iteratee, accumulator, initAccum) { 165 | var index = -1, 166 | length = array ? array.length : 0; 167 | 168 | if (initAccum && length) { 169 | accumulator = array[++index]; 170 | } 171 | while (++index < length) { 172 | accumulator = iteratee(accumulator, array[index], index, array); 173 | } 174 | return accumulator; 175 | } 176 | 177 | /** 178 | * Splits an ASCII `string` into an array of its words. 179 | * 180 | * @private 181 | * @param {string} The string to inspect. 182 | * @returns {Array} Returns the words of `string`. 183 | */ 184 | function asciiWords(string) { 185 | return string.match(reAsciiWord) || []; 186 | } 187 | 188 | /** 189 | * The base implementation of `_.propertyOf` without support for deep paths. 190 | * 191 | * @private 192 | * @param {Object} object The object to query. 193 | * @returns {Function} Returns the new accessor function. 194 | */ 195 | function basePropertyOf(object) { 196 | return function(key) { 197 | return object == null ? undefined : object[key]; 198 | }; 199 | } 200 | 201 | /** 202 | * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A 203 | * letters to basic Latin letters. 204 | * 205 | * @private 206 | * @param {string} letter The matched letter to deburr. 207 | * @returns {string} Returns the deburred letter. 208 | */ 209 | var deburrLetter = basePropertyOf(deburredLetters); 210 | 211 | /** 212 | * Checks if `string` contains a word composed of Unicode symbols. 213 | * 214 | * @private 215 | * @param {string} string The string to inspect. 216 | * @returns {boolean} Returns `true` if a word is found, else `false`. 217 | */ 218 | function hasUnicodeWord(string) { 219 | return reHasUnicodeWord.test(string); 220 | } 221 | 222 | /** 223 | * Splits a Unicode `string` into an array of its words. 224 | * 225 | * @private 226 | * @param {string} The string to inspect. 227 | * @returns {Array} Returns the words of `string`. 228 | */ 229 | function unicodeWords(string) { 230 | return string.match(reUnicodeWord) || []; 231 | } 232 | 233 | /** Used for built-in method references. */ 234 | var objectProto = Object.prototype; 235 | 236 | /** 237 | * Used to resolve the 238 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) 239 | * of values. 240 | */ 241 | var objectToString = objectProto.toString; 242 | 243 | /** Built-in value references. */ 244 | var Symbol = root.Symbol; 245 | 246 | /** Used to convert symbols to primitives and strings. */ 247 | var symbolProto = Symbol ? Symbol.prototype : undefined, 248 | symbolToString = symbolProto ? symbolProto.toString : undefined; 249 | 250 | /** 251 | * The base implementation of `_.toString` which doesn't convert nullish 252 | * values to empty strings. 253 | * 254 | * @private 255 | * @param {*} value The value to process. 256 | * @returns {string} Returns the string. 257 | */ 258 | function baseToString(value) { 259 | // Exit early for strings to avoid a performance hit in some environments. 260 | if (typeof value == 'string') { 261 | return value; 262 | } 263 | if (isSymbol(value)) { 264 | return symbolToString ? symbolToString.call(value) : ''; 265 | } 266 | var result = (value + ''); 267 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; 268 | } 269 | 270 | /** 271 | * Creates a function like `_.camelCase`. 272 | * 273 | * @private 274 | * @param {Function} callback The function to combine each word. 275 | * @returns {Function} Returns the new compounder function. 276 | */ 277 | function createCompounder(callback) { 278 | return function(string) { 279 | return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); 280 | }; 281 | } 282 | 283 | /** 284 | * Checks if `value` is object-like. A value is object-like if it's not `null` 285 | * and has a `typeof` result of "object". 286 | * 287 | * @static 288 | * @memberOf _ 289 | * @since 4.0.0 290 | * @category Lang 291 | * @param {*} value The value to check. 292 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`. 293 | * @example 294 | * 295 | * _.isObjectLike({}); 296 | * // => true 297 | * 298 | * _.isObjectLike([1, 2, 3]); 299 | * // => true 300 | * 301 | * _.isObjectLike(_.noop); 302 | * // => false 303 | * 304 | * _.isObjectLike(null); 305 | * // => false 306 | */ 307 | function isObjectLike(value) { 308 | return !!value && typeof value == 'object'; 309 | } 310 | 311 | /** 312 | * Checks if `value` is classified as a `Symbol` primitive or object. 313 | * 314 | * @static 315 | * @memberOf _ 316 | * @since 4.0.0 317 | * @category Lang 318 | * @param {*} value The value to check. 319 | * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. 320 | * @example 321 | * 322 | * _.isSymbol(Symbol.iterator); 323 | * // => true 324 | * 325 | * _.isSymbol('abc'); 326 | * // => false 327 | */ 328 | function isSymbol(value) { 329 | return typeof value == 'symbol' || 330 | (isObjectLike(value) && objectToString.call(value) == symbolTag); 331 | } 332 | 333 | /** 334 | * Converts `value` to a string. An empty string is returned for `null` 335 | * and `undefined` values. The sign of `-0` is preserved. 336 | * 337 | * @static 338 | * @memberOf _ 339 | * @since 4.0.0 340 | * @category Lang 341 | * @param {*} value The value to process. 342 | * @returns {string} Returns the string. 343 | * @example 344 | * 345 | * _.toString(null); 346 | * // => '' 347 | * 348 | * _.toString(-0); 349 | * // => '-0' 350 | * 351 | * _.toString([1, 2, 3]); 352 | * // => '1,2,3' 353 | */ 354 | function toString(value) { 355 | return value == null ? '' : baseToString(value); 356 | } 357 | 358 | /** 359 | * Deburrs `string` by converting 360 | * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) 361 | * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) 362 | * letters to basic Latin letters and removing 363 | * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). 364 | * 365 | * @static 366 | * @memberOf _ 367 | * @since 3.0.0 368 | * @category String 369 | * @param {string} [string=''] The string to deburr. 370 | * @returns {string} Returns the deburred string. 371 | * @example 372 | * 373 | * _.deburr('déjà vu'); 374 | * // => 'deja vu' 375 | */ 376 | function deburr(string) { 377 | string = toString(string); 378 | return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); 379 | } 380 | 381 | /** 382 | * Converts `string` to 383 | * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). 384 | * 385 | * @static 386 | * @memberOf _ 387 | * @since 3.0.0 388 | * @category String 389 | * @param {string} [string=''] The string to convert. 390 | * @returns {string} Returns the kebab cased string. 391 | * @example 392 | * 393 | * _.kebabCase('Foo Bar'); 394 | * // => 'foo-bar' 395 | * 396 | * _.kebabCase('fooBar'); 397 | * // => 'foo-bar' 398 | * 399 | * _.kebabCase('__FOO_BAR__'); 400 | * // => 'foo-bar' 401 | */ 402 | var kebabCase = createCompounder(function(result, word, index) { 403 | return result + (index ? '-' : '') + word.toLowerCase(); 404 | }); 405 | 406 | /** 407 | * Splits `string` into an array of its words. 408 | * 409 | * @static 410 | * @memberOf _ 411 | * @since 3.0.0 412 | * @category String 413 | * @param {string} [string=''] The string to inspect. 414 | * @param {RegExp|string} [pattern] The pattern to match words. 415 | * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 416 | * @returns {Array} Returns the words of `string`. 417 | * @example 418 | * 419 | * _.words('fred, barney, & pebbles'); 420 | * // => ['fred', 'barney', 'pebbles'] 421 | * 422 | * _.words('fred, barney, & pebbles', /[^, ]+/g); 423 | * // => ['fred', 'barney', '&', 'pebbles'] 424 | */ 425 | function words(string, pattern, guard) { 426 | string = toString(string); 427 | pattern = guard ? undefined : pattern; 428 | 429 | if (pattern === undefined) { 430 | return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); 431 | } 432 | return string.match(pattern) || []; 433 | } 434 | 435 | module.exports = kebabCase; 436 | -------------------------------------------------------------------------------- /node_modules/lodash.kebabcase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "lodash.kebabcase", 3 | "_id": "lodash.kebabcase@4.1.1", 4 | "_inBundle": false, 5 | "_integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", 6 | "_location": "/lodash.kebabcase", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "lodash.kebabcase", 12 | "name": "lodash.kebabcase", 13 | "escapedName": "lodash.kebabcase", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", 23 | "_shasum": "8489b1cb0d29ff88195cceca448ff6d6cc295c36", 24 | "_spec": "lodash.kebabcase", 25 | "_where": "/Users/jeff/Library/Application Support/StarUML/extensions/user/staruml-nestjs", 26 | "author": { 27 | "name": "John-David Dalton", 28 | "email": "john.david.dalton@gmail.com", 29 | "url": "http://allyoucanleet.com/" 30 | }, 31 | "bugs": { 32 | "url": "https://github.com/lodash/lodash/issues" 33 | }, 34 | "bundleDependencies": false, 35 | "contributors": [ 36 | { 37 | "name": "John-David Dalton", 38 | "email": "john.david.dalton@gmail.com", 39 | "url": "http://allyoucanleet.com/" 40 | }, 41 | { 42 | "name": "Blaine Bublitz", 43 | "email": "blaine.bublitz@gmail.com", 44 | "url": "https://github.com/phated" 45 | }, 46 | { 47 | "name": "Mathias Bynens", 48 | "email": "mathias@qiwi.be", 49 | "url": "https://mathiasbynens.be/" 50 | } 51 | ], 52 | "deprecated": false, 53 | "description": "The lodash method `_.kebabCase` exported as a module.", 54 | "homepage": "https://lodash.com/", 55 | "icon": "https://lodash.com/icon.svg", 56 | "keywords": [ 57 | "lodash-modularized", 58 | "kebabcase" 59 | ], 60 | "license": "MIT", 61 | "name": "lodash.kebabcase", 62 | "repository": { 63 | "type": "git", 64 | "url": "git+https://github.com/lodash/lodash.git" 65 | }, 66 | "scripts": { 67 | "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" 68 | }, 69 | "version": "4.1.1" 70 | } 71 | -------------------------------------------------------------------------------- /node_modules/lodash.snakecase/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors 2 | 3 | Based on Underscore.js, copyright Jeremy Ashkenas, 4 | DocumentCloud and Investigative Reporters & Editors 5 | 6 | This software consists of voluntary contributions made by many 7 | individuals. For exact contribution history, see the revision history 8 | available at https://github.com/lodash/lodash 9 | 10 | The following license applies to all parts of this software except as 11 | documented below: 12 | 13 | ==== 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining 16 | a copy of this software and associated documentation files (the 17 | "Software"), to deal in the Software without restriction, including 18 | without limitation the rights to use, copy, modify, merge, publish, 19 | distribute, sublicense, and/or sell copies of the Software, and to 20 | permit persons to whom the Software is furnished to do so, subject to 21 | the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be 24 | included in all copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 | 34 | ==== 35 | 36 | Copyright and related rights for sample code are waived via CC0. Sample 37 | code is defined as all source code displayed within the prose of the 38 | documentation. 39 | 40 | CC0: http://creativecommons.org/publicdomain/zero/1.0/ 41 | 42 | ==== 43 | 44 | Files located in the node_modules and vendor directories are externally 45 | maintained libraries used by this software which have their own 46 | licenses; we recommend you read them, as their terms may differ from the 47 | terms above. 48 | -------------------------------------------------------------------------------- /node_modules/lodash.snakecase/README.md: -------------------------------------------------------------------------------- 1 | # lodash.snakecase v4.1.1 2 | 3 | The [lodash](https://lodash.com/) method `_.snakeCase` exported as a [Node.js](https://nodejs.org/) module. 4 | 5 | ## Installation 6 | 7 | Using npm: 8 | ```bash 9 | $ {sudo -H} npm i -g npm 10 | $ npm i --save lodash.snakecase 11 | ``` 12 | 13 | In Node.js: 14 | ```js 15 | var snakeCase = require('lodash.snakecase'); 16 | ``` 17 | 18 | See the [documentation](https://lodash.com/docs#snakeCase) or [package source](https://github.com/lodash/lodash/blob/4.1.1-npm-packages/lodash.snakecase) for more details. 19 | -------------------------------------------------------------------------------- /node_modules/lodash.snakecase/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lodash (Custom Build) 3 | * Build: `lodash modularize exports="npm" -o ./` 4 | * Copyright jQuery Foundation and other contributors 5 | * Released under MIT license 6 | * Based on Underscore.js 1.8.3 7 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 8 | */ 9 | 10 | /** Used as references for various `Number` constants. */ 11 | var INFINITY = 1 / 0; 12 | 13 | /** `Object#toString` result references. */ 14 | var symbolTag = '[object Symbol]'; 15 | 16 | /** Used to match words composed of alphanumeric characters. */ 17 | var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; 18 | 19 | /** Used to match Latin Unicode letters (excluding mathematical operators). */ 20 | var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; 21 | 22 | /** Used to compose unicode character classes. */ 23 | var rsAstralRange = '\\ud800-\\udfff', 24 | rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', 25 | rsComboSymbolsRange = '\\u20d0-\\u20f0', 26 | rsDingbatRange = '\\u2700-\\u27bf', 27 | rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', 28 | rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', 29 | rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', 30 | rsPunctuationRange = '\\u2000-\\u206f', 31 | rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', 32 | rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', 33 | rsVarRange = '\\ufe0e\\ufe0f', 34 | rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; 35 | 36 | /** Used to compose unicode capture groups. */ 37 | var rsApos = "['\u2019]", 38 | rsBreak = '[' + rsBreakRange + ']', 39 | rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', 40 | rsDigits = '\\d+', 41 | rsDingbat = '[' + rsDingbatRange + ']', 42 | rsLower = '[' + rsLowerRange + ']', 43 | rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', 44 | rsFitz = '\\ud83c[\\udffb-\\udfff]', 45 | rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', 46 | rsNonAstral = '[^' + rsAstralRange + ']', 47 | rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', 48 | rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', 49 | rsUpper = '[' + rsUpperRange + ']', 50 | rsZWJ = '\\u200d'; 51 | 52 | /** Used to compose unicode regexes. */ 53 | var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', 54 | rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', 55 | rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', 56 | rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', 57 | reOptMod = rsModifier + '?', 58 | rsOptVar = '[' + rsVarRange + ']?', 59 | rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', 60 | rsSeq = rsOptVar + reOptMod + rsOptJoin, 61 | rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq; 62 | 63 | /** Used to match apostrophes. */ 64 | var reApos = RegExp(rsApos, 'g'); 65 | 66 | /** 67 | * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and 68 | * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). 69 | */ 70 | var reComboMark = RegExp(rsCombo, 'g'); 71 | 72 | /** Used to match complex or compound words. */ 73 | var reUnicodeWord = RegExp([ 74 | rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', 75 | rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', 76 | rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, 77 | rsUpper + '+' + rsOptUpperContr, 78 | rsDigits, 79 | rsEmoji 80 | ].join('|'), 'g'); 81 | 82 | /** Used to detect strings that need a more robust regexp to match words. */ 83 | var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; 84 | 85 | /** Used to map Latin Unicode letters to basic Latin letters. */ 86 | var deburredLetters = { 87 | // Latin-1 Supplement block. 88 | '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', 89 | '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', 90 | '\xc7': 'C', '\xe7': 'c', 91 | '\xd0': 'D', '\xf0': 'd', 92 | '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', 93 | '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', 94 | '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', 95 | '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', 96 | '\xd1': 'N', '\xf1': 'n', 97 | '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', 98 | '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', 99 | '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', 100 | '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', 101 | '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', 102 | '\xc6': 'Ae', '\xe6': 'ae', 103 | '\xde': 'Th', '\xfe': 'th', 104 | '\xdf': 'ss', 105 | // Latin Extended-A block. 106 | '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', 107 | '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', 108 | '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', 109 | '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', 110 | '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', 111 | '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', 112 | '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', 113 | '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', 114 | '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', 115 | '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', 116 | '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', 117 | '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', 118 | '\u0134': 'J', '\u0135': 'j', 119 | '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', 120 | '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', 121 | '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', 122 | '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', 123 | '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', 124 | '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', 125 | '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', 126 | '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', 127 | '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', 128 | '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', 129 | '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', 130 | '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', 131 | '\u0163': 't', '\u0165': 't', '\u0167': 't', 132 | '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', 133 | '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', 134 | '\u0174': 'W', '\u0175': 'w', 135 | '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', 136 | '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', 137 | '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', 138 | '\u0132': 'IJ', '\u0133': 'ij', 139 | '\u0152': 'Oe', '\u0153': 'oe', 140 | '\u0149': "'n", '\u017f': 'ss' 141 | }; 142 | 143 | /** Detect free variable `global` from Node.js. */ 144 | var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; 145 | 146 | /** Detect free variable `self`. */ 147 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self; 148 | 149 | /** Used as a reference to the global object. */ 150 | var root = freeGlobal || freeSelf || Function('return this')(); 151 | 152 | /** 153 | * A specialized version of `_.reduce` for arrays without support for 154 | * iteratee shorthands. 155 | * 156 | * @private 157 | * @param {Array} [array] The array to iterate over. 158 | * @param {Function} iteratee The function invoked per iteration. 159 | * @param {*} [accumulator] The initial value. 160 | * @param {boolean} [initAccum] Specify using the first element of `array` as 161 | * the initial value. 162 | * @returns {*} Returns the accumulated value. 163 | */ 164 | function arrayReduce(array, iteratee, accumulator, initAccum) { 165 | var index = -1, 166 | length = array ? array.length : 0; 167 | 168 | if (initAccum && length) { 169 | accumulator = array[++index]; 170 | } 171 | while (++index < length) { 172 | accumulator = iteratee(accumulator, array[index], index, array); 173 | } 174 | return accumulator; 175 | } 176 | 177 | /** 178 | * Splits an ASCII `string` into an array of its words. 179 | * 180 | * @private 181 | * @param {string} The string to inspect. 182 | * @returns {Array} Returns the words of `string`. 183 | */ 184 | function asciiWords(string) { 185 | return string.match(reAsciiWord) || []; 186 | } 187 | 188 | /** 189 | * The base implementation of `_.propertyOf` without support for deep paths. 190 | * 191 | * @private 192 | * @param {Object} object The object to query. 193 | * @returns {Function} Returns the new accessor function. 194 | */ 195 | function basePropertyOf(object) { 196 | return function(key) { 197 | return object == null ? undefined : object[key]; 198 | }; 199 | } 200 | 201 | /** 202 | * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A 203 | * letters to basic Latin letters. 204 | * 205 | * @private 206 | * @param {string} letter The matched letter to deburr. 207 | * @returns {string} Returns the deburred letter. 208 | */ 209 | var deburrLetter = basePropertyOf(deburredLetters); 210 | 211 | /** 212 | * Checks if `string` contains a word composed of Unicode symbols. 213 | * 214 | * @private 215 | * @param {string} string The string to inspect. 216 | * @returns {boolean} Returns `true` if a word is found, else `false`. 217 | */ 218 | function hasUnicodeWord(string) { 219 | return reHasUnicodeWord.test(string); 220 | } 221 | 222 | /** 223 | * Splits a Unicode `string` into an array of its words. 224 | * 225 | * @private 226 | * @param {string} The string to inspect. 227 | * @returns {Array} Returns the words of `string`. 228 | */ 229 | function unicodeWords(string) { 230 | return string.match(reUnicodeWord) || []; 231 | } 232 | 233 | /** Used for built-in method references. */ 234 | var objectProto = Object.prototype; 235 | 236 | /** 237 | * Used to resolve the 238 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) 239 | * of values. 240 | */ 241 | var objectToString = objectProto.toString; 242 | 243 | /** Built-in value references. */ 244 | var Symbol = root.Symbol; 245 | 246 | /** Used to convert symbols to primitives and strings. */ 247 | var symbolProto = Symbol ? Symbol.prototype : undefined, 248 | symbolToString = symbolProto ? symbolProto.toString : undefined; 249 | 250 | /** 251 | * The base implementation of `_.toString` which doesn't convert nullish 252 | * values to empty strings. 253 | * 254 | * @private 255 | * @param {*} value The value to process. 256 | * @returns {string} Returns the string. 257 | */ 258 | function baseToString(value) { 259 | // Exit early for strings to avoid a performance hit in some environments. 260 | if (typeof value == 'string') { 261 | return value; 262 | } 263 | if (isSymbol(value)) { 264 | return symbolToString ? symbolToString.call(value) : ''; 265 | } 266 | var result = (value + ''); 267 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; 268 | } 269 | 270 | /** 271 | * Creates a function like `_.camelCase`. 272 | * 273 | * @private 274 | * @param {Function} callback The function to combine each word. 275 | * @returns {Function} Returns the new compounder function. 276 | */ 277 | function createCompounder(callback) { 278 | return function(string) { 279 | return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); 280 | }; 281 | } 282 | 283 | /** 284 | * Checks if `value` is object-like. A value is object-like if it's not `null` 285 | * and has a `typeof` result of "object". 286 | * 287 | * @static 288 | * @memberOf _ 289 | * @since 4.0.0 290 | * @category Lang 291 | * @param {*} value The value to check. 292 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`. 293 | * @example 294 | * 295 | * _.isObjectLike({}); 296 | * // => true 297 | * 298 | * _.isObjectLike([1, 2, 3]); 299 | * // => true 300 | * 301 | * _.isObjectLike(_.noop); 302 | * // => false 303 | * 304 | * _.isObjectLike(null); 305 | * // => false 306 | */ 307 | function isObjectLike(value) { 308 | return !!value && typeof value == 'object'; 309 | } 310 | 311 | /** 312 | * Checks if `value` is classified as a `Symbol` primitive or object. 313 | * 314 | * @static 315 | * @memberOf _ 316 | * @since 4.0.0 317 | * @category Lang 318 | * @param {*} value The value to check. 319 | * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. 320 | * @example 321 | * 322 | * _.isSymbol(Symbol.iterator); 323 | * // => true 324 | * 325 | * _.isSymbol('abc'); 326 | * // => false 327 | */ 328 | function isSymbol(value) { 329 | return typeof value == 'symbol' || 330 | (isObjectLike(value) && objectToString.call(value) == symbolTag); 331 | } 332 | 333 | /** 334 | * Converts `value` to a string. An empty string is returned for `null` 335 | * and `undefined` values. The sign of `-0` is preserved. 336 | * 337 | * @static 338 | * @memberOf _ 339 | * @since 4.0.0 340 | * @category Lang 341 | * @param {*} value The value to process. 342 | * @returns {string} Returns the string. 343 | * @example 344 | * 345 | * _.toString(null); 346 | * // => '' 347 | * 348 | * _.toString(-0); 349 | * // => '-0' 350 | * 351 | * _.toString([1, 2, 3]); 352 | * // => '1,2,3' 353 | */ 354 | function toString(value) { 355 | return value == null ? '' : baseToString(value); 356 | } 357 | 358 | /** 359 | * Deburrs `string` by converting 360 | * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) 361 | * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) 362 | * letters to basic Latin letters and removing 363 | * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). 364 | * 365 | * @static 366 | * @memberOf _ 367 | * @since 3.0.0 368 | * @category String 369 | * @param {string} [string=''] The string to deburr. 370 | * @returns {string} Returns the deburred string. 371 | * @example 372 | * 373 | * _.deburr('déjà vu'); 374 | * // => 'deja vu' 375 | */ 376 | function deburr(string) { 377 | string = toString(string); 378 | return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); 379 | } 380 | 381 | /** 382 | * Converts `string` to 383 | * [snake case](https://en.wikipedia.org/wiki/Snake_case). 384 | * 385 | * @static 386 | * @memberOf _ 387 | * @since 3.0.0 388 | * @category String 389 | * @param {string} [string=''] The string to convert. 390 | * @returns {string} Returns the snake cased string. 391 | * @example 392 | * 393 | * _.snakeCase('Foo Bar'); 394 | * // => 'foo_bar' 395 | * 396 | * _.snakeCase('fooBar'); 397 | * // => 'foo_bar' 398 | * 399 | * _.snakeCase('--FOO-BAR--'); 400 | * // => 'foo_bar' 401 | */ 402 | var snakeCase = createCompounder(function(result, word, index) { 403 | return result + (index ? '_' : '') + word.toLowerCase(); 404 | }); 405 | 406 | /** 407 | * Splits `string` into an array of its words. 408 | * 409 | * @static 410 | * @memberOf _ 411 | * @since 3.0.0 412 | * @category String 413 | * @param {string} [string=''] The string to inspect. 414 | * @param {RegExp|string} [pattern] The pattern to match words. 415 | * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 416 | * @returns {Array} Returns the words of `string`. 417 | * @example 418 | * 419 | * _.words('fred, barney, & pebbles'); 420 | * // => ['fred', 'barney', 'pebbles'] 421 | * 422 | * _.words('fred, barney, & pebbles', /[^, ]+/g); 423 | * // => ['fred', 'barney', '&', 'pebbles'] 424 | */ 425 | function words(string, pattern, guard) { 426 | string = toString(string); 427 | pattern = guard ? undefined : pattern; 428 | 429 | if (pattern === undefined) { 430 | return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); 431 | } 432 | return string.match(pattern) || []; 433 | } 434 | 435 | module.exports = snakeCase; 436 | -------------------------------------------------------------------------------- /node_modules/lodash.snakecase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "lodash.snakecase", 3 | "_id": "lodash.snakecase@4.1.1", 4 | "_inBundle": false, 5 | "_integrity": "sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=", 6 | "_location": "/lodash.snakecase", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "lodash.snakecase", 12 | "name": "lodash.snakecase", 13 | "escapedName": "lodash.snakecase", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", 23 | "_shasum": "39d714a35357147837aefd64b5dcbb16becd8f8d", 24 | "_spec": "lodash.snakecase", 25 | "_where": "/Users/jeff/Library/Application Support/StarUML/extensions/user/staruml-nestjs", 26 | "author": { 27 | "name": "John-David Dalton", 28 | "email": "john.david.dalton@gmail.com", 29 | "url": "http://allyoucanleet.com/" 30 | }, 31 | "bugs": { 32 | "url": "https://github.com/lodash/lodash/issues" 33 | }, 34 | "bundleDependencies": false, 35 | "contributors": [ 36 | { 37 | "name": "John-David Dalton", 38 | "email": "john.david.dalton@gmail.com", 39 | "url": "http://allyoucanleet.com/" 40 | }, 41 | { 42 | "name": "Blaine Bublitz", 43 | "email": "blaine.bublitz@gmail.com", 44 | "url": "https://github.com/phated" 45 | }, 46 | { 47 | "name": "Mathias Bynens", 48 | "email": "mathias@qiwi.be", 49 | "url": "https://mathiasbynens.be/" 50 | } 51 | ], 52 | "deprecated": false, 53 | "description": "The lodash method `_.snakeCase` exported as a module.", 54 | "homepage": "https://lodash.com/", 55 | "icon": "https://lodash.com/icon.svg", 56 | "keywords": [ 57 | "lodash-modularized", 58 | "snakecase" 59 | ], 60 | "license": "MIT", 61 | "name": "lodash.snakecase", 62 | "repository": { 63 | "type": "git", 64 | "url": "git+https://github.com/lodash/lodash.git" 65 | }, 66 | "scripts": { 67 | "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" 68 | }, 69 | "version": "4.1.1" 70 | } 71 | -------------------------------------------------------------------------------- /node_modules/pluralize/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Blake Embrey (hello@blakeembrey.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /node_modules/pluralize/Readme.md: -------------------------------------------------------------------------------- 1 | # Pluralize 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![NPM downloads][downloads-image]][downloads-url] 5 | [![Build status][travis-image]][travis-url] 6 | [![Test coverage][coveralls-image]][coveralls-url] 7 | ![File Size][filesize-url] 8 | [![CDNJS][cdnjs-image]][cdnjs-url] 9 | 10 | > Pluralize and singularize any word. 11 | 12 | ## Installation 13 | 14 | ``` 15 | npm install pluralize --save 16 | yarn add pluralize 17 | bower install pluralize --save 18 | ``` 19 | 20 | ### Node 21 | 22 | ```javascript 23 | var pluralize = require('pluralize') 24 | ``` 25 | 26 | ### AMD 27 | 28 | ```javascript 29 | define(function (require, exports, module) { 30 | var pluralize = require('pluralize') 31 | }) 32 | ``` 33 | 34 | ### ` 38 | ``` 39 | 40 | ## Why? 41 | 42 | This module uses a pre-defined list of rules, applied in order, to singularize or pluralize a given word. There are many cases where this is useful, such as any automation based on user input. For applications where the word(s) are known ahead of time, you can use a simple ternary (or function) which would be a much lighter alternative. 43 | 44 | ## Usage 45 | 46 | * `word: string` The word to pluralize 47 | * `count: number` How many of the word exist 48 | * `inclusive: boolean` Whether to prefix with the number (e.g. 3 ducks) 49 | 50 | Examples: 51 | 52 | ```javascript 53 | pluralize('test') //=> "tests" 54 | pluralize('test', 0) //=> "tests" 55 | pluralize('test', 1) //=> "test" 56 | pluralize('test', 5) //=> "tests" 57 | pluralize('test', 1, true) //=> "1 test" 58 | pluralize('test', 5, true) //=> "5 tests" 59 | pluralize('蘋果', 2, true) //=> "2 蘋果" 60 | 61 | // Example of new plural rule: 62 | pluralize.plural('regex') //=> "regexes" 63 | pluralize.addPluralRule(/gex$/i, 'gexii') 64 | pluralize.plural('regex') //=> "regexii" 65 | 66 | // Example of new singular rule: 67 | pluralize.singular('singles') //=> "single" 68 | pluralize.addSingularRule(/singles$/i, 'singular') 69 | pluralize.singular('singles') //=> "singular" 70 | 71 | // Example of new irregular rule, e.g. "I" -> "we": 72 | pluralize.plural('irregular') //=> "irregulars" 73 | pluralize.addIrregularRule('irregular', 'regular') 74 | pluralize.plural('irregular') //=> "regular" 75 | 76 | // Example of uncountable rule (rules without singular/plural in context): 77 | pluralize.plural('paper') //=> "papers" 78 | pluralize.addUncountableRule('paper') 79 | pluralize.plural('paper') //=> "paper" 80 | 81 | // Example of asking whether a word looks singular or plural: 82 | pluralize.isPlural('test') //=> false 83 | pluralize.isSingular('test') //=> true 84 | ``` 85 | 86 | ## License 87 | 88 | MIT 89 | 90 | [npm-image]: https://img.shields.io/npm/v/pluralize.svg?style=flat 91 | [npm-url]: https://npmjs.org/package/pluralize 92 | [downloads-image]: https://img.shields.io/npm/dm/pluralize.svg?style=flat 93 | [downloads-url]: https://npmjs.org/package/pluralize 94 | [travis-image]: https://img.shields.io/travis/blakeembrey/pluralize.svg?style=flat 95 | [travis-url]: https://travis-ci.org/blakeembrey/pluralize 96 | [coveralls-image]: https://img.shields.io/coveralls/blakeembrey/pluralize.svg?style=flat 97 | [coveralls-url]: https://coveralls.io/r/blakeembrey/pluralize?branch=master 98 | [filesize-url]: https://img.shields.io/github/size/blakeembrey/pluralize/pluralize.js.svg?style=flat 99 | [cdnjs-image]: https://img.shields.io/cdnjs/v/pluralize.svg 100 | [cdnjs-url]: https://cdnjs.com/libraries/pluralize 101 | -------------------------------------------------------------------------------- /node_modules/pluralize/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "pluralize", 3 | "_id": "pluralize@8.0.0", 4 | "_inBundle": false, 5 | "_integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", 6 | "_location": "/pluralize", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "pluralize", 12 | "name": "pluralize", 13 | "escapedName": "pluralize", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", 23 | "_shasum": "1a6fa16a38d12a1901e0320fa017051c539ce3b1", 24 | "_spec": "pluralize", 25 | "_where": "/Users/jeff/Library/Application Support/StarUML/extensions/user/staruml-nestjs", 26 | "author": { 27 | "name": "Blake Embrey", 28 | "email": "hello@blakeembrey.com", 29 | "url": "http://blakeembrey.me" 30 | }, 31 | "bugs": { 32 | "url": "https://github.com/blakeembrey/pluralize/issues" 33 | }, 34 | "bundleDependencies": false, 35 | "deprecated": false, 36 | "description": "Pluralize and singularize any word", 37 | "devDependencies": { 38 | "chai": "^4.0.0", 39 | "istanbul": "^0.4.5", 40 | "mocha": "^5.0.0", 41 | "semistandard": "^12.0.0" 42 | }, 43 | "engines": { 44 | "node": ">=4" 45 | }, 46 | "files": [ 47 | "pluralize.js" 48 | ], 49 | "homepage": "https://github.com/blakeembrey/pluralize#readme", 50 | "keywords": [ 51 | "plural", 52 | "plurals", 53 | "pluralize", 54 | "singular", 55 | "singularize", 56 | "inflection" 57 | ], 58 | "license": "MIT", 59 | "main": "pluralize.js", 60 | "name": "pluralize", 61 | "repository": { 62 | "type": "git", 63 | "url": "git+https://github.com/blakeembrey/pluralize.git" 64 | }, 65 | "scripts": { 66 | "lint": "semistandard", 67 | "test": "npm run lint && npm run test-cov", 68 | "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- -R spec --bail", 69 | "test-spec": "mocha -R spec --bail" 70 | }, 71 | "version": "8.0.0" 72 | } 73 | -------------------------------------------------------------------------------- /node_modules/pluralize/pluralize.js: -------------------------------------------------------------------------------- 1 | /* global define */ 2 | 3 | (function (root, pluralize) { 4 | /* istanbul ignore else */ 5 | if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') { 6 | // Node. 7 | module.exports = pluralize(); 8 | } else if (typeof define === 'function' && define.amd) { 9 | // AMD, registers as an anonymous module. 10 | define(function () { 11 | return pluralize(); 12 | }); 13 | } else { 14 | // Browser global. 15 | root.pluralize = pluralize(); 16 | } 17 | })(this, function () { 18 | // Rule storage - pluralize and singularize need to be run sequentially, 19 | // while other rules can be optimized using an object for instant lookups. 20 | var pluralRules = []; 21 | var singularRules = []; 22 | var uncountables = {}; 23 | var irregularPlurals = {}; 24 | var irregularSingles = {}; 25 | 26 | /** 27 | * Sanitize a pluralization rule to a usable regular expression. 28 | * 29 | * @param {(RegExp|string)} rule 30 | * @return {RegExp} 31 | */ 32 | function sanitizeRule (rule) { 33 | if (typeof rule === 'string') { 34 | return new RegExp('^' + rule + '$', 'i'); 35 | } 36 | 37 | return rule; 38 | } 39 | 40 | /** 41 | * Pass in a word token to produce a function that can replicate the case on 42 | * another word. 43 | * 44 | * @param {string} word 45 | * @param {string} token 46 | * @return {Function} 47 | */ 48 | function restoreCase (word, token) { 49 | // Tokens are an exact match. 50 | if (word === token) return token; 51 | 52 | // Lower cased words. E.g. "hello". 53 | if (word === word.toLowerCase()) return token.toLowerCase(); 54 | 55 | // Upper cased words. E.g. "WHISKY". 56 | if (word === word.toUpperCase()) return token.toUpperCase(); 57 | 58 | // Title cased words. E.g. "Title". 59 | if (word[0] === word[0].toUpperCase()) { 60 | return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase(); 61 | } 62 | 63 | // Lower cased words. E.g. "test". 64 | return token.toLowerCase(); 65 | } 66 | 67 | /** 68 | * Interpolate a regexp string. 69 | * 70 | * @param {string} str 71 | * @param {Array} args 72 | * @return {string} 73 | */ 74 | function interpolate (str, args) { 75 | return str.replace(/\$(\d{1,2})/g, function (match, index) { 76 | return args[index] || ''; 77 | }); 78 | } 79 | 80 | /** 81 | * Replace a word using a rule. 82 | * 83 | * @param {string} word 84 | * @param {Array} rule 85 | * @return {string} 86 | */ 87 | function replace (word, rule) { 88 | return word.replace(rule[0], function (match, index) { 89 | var result = interpolate(rule[1], arguments); 90 | 91 | if (match === '') { 92 | return restoreCase(word[index - 1], result); 93 | } 94 | 95 | return restoreCase(match, result); 96 | }); 97 | } 98 | 99 | /** 100 | * Sanitize a word by passing in the word and sanitization rules. 101 | * 102 | * @param {string} token 103 | * @param {string} word 104 | * @param {Array} rules 105 | * @return {string} 106 | */ 107 | function sanitizeWord (token, word, rules) { 108 | // Empty string or doesn't need fixing. 109 | if (!token.length || uncountables.hasOwnProperty(token)) { 110 | return word; 111 | } 112 | 113 | var len = rules.length; 114 | 115 | // Iterate over the sanitization rules and use the first one to match. 116 | while (len--) { 117 | var rule = rules[len]; 118 | 119 | if (rule[0].test(word)) return replace(word, rule); 120 | } 121 | 122 | return word; 123 | } 124 | 125 | /** 126 | * Replace a word with the updated word. 127 | * 128 | * @param {Object} replaceMap 129 | * @param {Object} keepMap 130 | * @param {Array} rules 131 | * @return {Function} 132 | */ 133 | function replaceWord (replaceMap, keepMap, rules) { 134 | return function (word) { 135 | // Get the correct token and case restoration functions. 136 | var token = word.toLowerCase(); 137 | 138 | // Check against the keep object map. 139 | if (keepMap.hasOwnProperty(token)) { 140 | return restoreCase(word, token); 141 | } 142 | 143 | // Check against the replacement map for a direct word replacement. 144 | if (replaceMap.hasOwnProperty(token)) { 145 | return restoreCase(word, replaceMap[token]); 146 | } 147 | 148 | // Run all the rules against the word. 149 | return sanitizeWord(token, word, rules); 150 | }; 151 | } 152 | 153 | /** 154 | * Check if a word is part of the map. 155 | */ 156 | function checkWord (replaceMap, keepMap, rules, bool) { 157 | return function (word) { 158 | var token = word.toLowerCase(); 159 | 160 | if (keepMap.hasOwnProperty(token)) return true; 161 | if (replaceMap.hasOwnProperty(token)) return false; 162 | 163 | return sanitizeWord(token, token, rules) === token; 164 | }; 165 | } 166 | 167 | /** 168 | * Pluralize or singularize a word based on the passed in count. 169 | * 170 | * @param {string} word The word to pluralize 171 | * @param {number} count How many of the word exist 172 | * @param {boolean} inclusive Whether to prefix with the number (e.g. 3 ducks) 173 | * @return {string} 174 | */ 175 | function pluralize (word, count, inclusive) { 176 | var pluralized = count === 1 177 | ? pluralize.singular(word) : pluralize.plural(word); 178 | 179 | return (inclusive ? count + ' ' : '') + pluralized; 180 | } 181 | 182 | /** 183 | * Pluralize a word. 184 | * 185 | * @type {Function} 186 | */ 187 | pluralize.plural = replaceWord( 188 | irregularSingles, irregularPlurals, pluralRules 189 | ); 190 | 191 | /** 192 | * Check if a word is plural. 193 | * 194 | * @type {Function} 195 | */ 196 | pluralize.isPlural = checkWord( 197 | irregularSingles, irregularPlurals, pluralRules 198 | ); 199 | 200 | /** 201 | * Singularize a word. 202 | * 203 | * @type {Function} 204 | */ 205 | pluralize.singular = replaceWord( 206 | irregularPlurals, irregularSingles, singularRules 207 | ); 208 | 209 | /** 210 | * Check if a word is singular. 211 | * 212 | * @type {Function} 213 | */ 214 | pluralize.isSingular = checkWord( 215 | irregularPlurals, irregularSingles, singularRules 216 | ); 217 | 218 | /** 219 | * Add a pluralization rule to the collection. 220 | * 221 | * @param {(string|RegExp)} rule 222 | * @param {string} replacement 223 | */ 224 | pluralize.addPluralRule = function (rule, replacement) { 225 | pluralRules.push([sanitizeRule(rule), replacement]); 226 | }; 227 | 228 | /** 229 | * Add a singularization rule to the collection. 230 | * 231 | * @param {(string|RegExp)} rule 232 | * @param {string} replacement 233 | */ 234 | pluralize.addSingularRule = function (rule, replacement) { 235 | singularRules.push([sanitizeRule(rule), replacement]); 236 | }; 237 | 238 | /** 239 | * Add an uncountable word rule. 240 | * 241 | * @param {(string|RegExp)} word 242 | */ 243 | pluralize.addUncountableRule = function (word) { 244 | if (typeof word === 'string') { 245 | uncountables[word.toLowerCase()] = true; 246 | return; 247 | } 248 | 249 | // Set singular and plural references for the word. 250 | pluralize.addPluralRule(word, '$0'); 251 | pluralize.addSingularRule(word, '$0'); 252 | }; 253 | 254 | /** 255 | * Add an irregular word definition. 256 | * 257 | * @param {string} single 258 | * @param {string} plural 259 | */ 260 | pluralize.addIrregularRule = function (single, plural) { 261 | plural = plural.toLowerCase(); 262 | single = single.toLowerCase(); 263 | 264 | irregularSingles[single] = plural; 265 | irregularPlurals[plural] = single; 266 | }; 267 | 268 | /** 269 | * Irregular rules. 270 | */ 271 | [ 272 | // Pronouns. 273 | ['I', 'we'], 274 | ['me', 'us'], 275 | ['he', 'they'], 276 | ['she', 'they'], 277 | ['them', 'them'], 278 | ['myself', 'ourselves'], 279 | ['yourself', 'yourselves'], 280 | ['itself', 'themselves'], 281 | ['herself', 'themselves'], 282 | ['himself', 'themselves'], 283 | ['themself', 'themselves'], 284 | ['is', 'are'], 285 | ['was', 'were'], 286 | ['has', 'have'], 287 | ['this', 'these'], 288 | ['that', 'those'], 289 | // Words ending in with a consonant and `o`. 290 | ['echo', 'echoes'], 291 | ['dingo', 'dingoes'], 292 | ['volcano', 'volcanoes'], 293 | ['tornado', 'tornadoes'], 294 | ['torpedo', 'torpedoes'], 295 | // Ends with `us`. 296 | ['genus', 'genera'], 297 | ['viscus', 'viscera'], 298 | // Ends with `ma`. 299 | ['stigma', 'stigmata'], 300 | ['stoma', 'stomata'], 301 | ['dogma', 'dogmata'], 302 | ['lemma', 'lemmata'], 303 | ['schema', 'schemata'], 304 | ['anathema', 'anathemata'], 305 | // Other irregular rules. 306 | ['ox', 'oxen'], 307 | ['axe', 'axes'], 308 | ['die', 'dice'], 309 | ['yes', 'yeses'], 310 | ['foot', 'feet'], 311 | ['eave', 'eaves'], 312 | ['goose', 'geese'], 313 | ['tooth', 'teeth'], 314 | ['quiz', 'quizzes'], 315 | ['human', 'humans'], 316 | ['proof', 'proofs'], 317 | ['carve', 'carves'], 318 | ['valve', 'valves'], 319 | ['looey', 'looies'], 320 | ['thief', 'thieves'], 321 | ['groove', 'grooves'], 322 | ['pickaxe', 'pickaxes'], 323 | ['passerby', 'passersby'] 324 | ].forEach(function (rule) { 325 | return pluralize.addIrregularRule(rule[0], rule[1]); 326 | }); 327 | 328 | /** 329 | * Pluralization rules. 330 | */ 331 | [ 332 | [/s?$/i, 's'], 333 | [/[^\u0000-\u007F]$/i, '$0'], 334 | [/([^aeiou]ese)$/i, '$1'], 335 | [/(ax|test)is$/i, '$1es'], 336 | [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, '$1es'], 337 | [/(e[mn]u)s?$/i, '$1s'], 338 | [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, '$1'], 339 | [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'], 340 | [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'], 341 | [/(seraph|cherub)(?:im)?$/i, '$1im'], 342 | [/(her|at|gr)o$/i, '$1oes'], 343 | [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'], 344 | [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'], 345 | [/sis$/i, 'ses'], 346 | [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'], 347 | [/([^aeiouy]|qu)y$/i, '$1ies'], 348 | [/([^ch][ieo][ln])ey$/i, '$1ies'], 349 | [/(x|ch|ss|sh|zz)$/i, '$1es'], 350 | [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'], 351 | [/\b((?:tit)?m|l)(?:ice|ouse)$/i, '$1ice'], 352 | [/(pe)(?:rson|ople)$/i, '$1ople'], 353 | [/(child)(?:ren)?$/i, '$1ren'], 354 | [/eaux$/i, '$0'], 355 | [/m[ae]n$/i, 'men'], 356 | ['thou', 'you'] 357 | ].forEach(function (rule) { 358 | return pluralize.addPluralRule(rule[0], rule[1]); 359 | }); 360 | 361 | /** 362 | * Singularization rules. 363 | */ 364 | [ 365 | [/s$/i, ''], 366 | [/(ss)$/i, '$1'], 367 | [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'], 368 | [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'], 369 | [/ies$/i, 'y'], 370 | [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, '$1ie'], 371 | [/\b(mon|smil)ies$/i, '$1ey'], 372 | [/\b((?:tit)?m|l)ice$/i, '$1ouse'], 373 | [/(seraph|cherub)im$/i, '$1'], 374 | [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, '$1'], 375 | [/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, '$1sis'], 376 | [/(movie|twelve|abuse|e[mn]u)s$/i, '$1'], 377 | [/(test)(?:is|es)$/i, '$1is'], 378 | [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'], 379 | [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'], 380 | [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'], 381 | [/(alumn|alg|vertebr)ae$/i, '$1a'], 382 | [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'], 383 | [/(matr|append)ices$/i, '$1ix'], 384 | [/(pe)(rson|ople)$/i, '$1rson'], 385 | [/(child)ren$/i, '$1'], 386 | [/(eau)x?$/i, '$1'], 387 | [/men$/i, 'man'] 388 | ].forEach(function (rule) { 389 | return pluralize.addSingularRule(rule[0], rule[1]); 390 | }); 391 | 392 | /** 393 | * Uncountable rules. 394 | */ 395 | [ 396 | // Singular words with no plurals. 397 | 'adulthood', 398 | 'advice', 399 | 'agenda', 400 | 'aid', 401 | 'aircraft', 402 | 'alcohol', 403 | 'ammo', 404 | 'analytics', 405 | 'anime', 406 | 'athletics', 407 | 'audio', 408 | 'bison', 409 | 'blood', 410 | 'bream', 411 | 'buffalo', 412 | 'butter', 413 | 'carp', 414 | 'cash', 415 | 'chassis', 416 | 'chess', 417 | 'clothing', 418 | 'cod', 419 | 'commerce', 420 | 'cooperation', 421 | 'corps', 422 | 'debris', 423 | 'diabetes', 424 | 'digestion', 425 | 'elk', 426 | 'energy', 427 | 'equipment', 428 | 'excretion', 429 | 'expertise', 430 | 'firmware', 431 | 'flounder', 432 | 'fun', 433 | 'gallows', 434 | 'garbage', 435 | 'graffiti', 436 | 'hardware', 437 | 'headquarters', 438 | 'health', 439 | 'herpes', 440 | 'highjinks', 441 | 'homework', 442 | 'housework', 443 | 'information', 444 | 'jeans', 445 | 'justice', 446 | 'kudos', 447 | 'labour', 448 | 'literature', 449 | 'machinery', 450 | 'mackerel', 451 | 'mail', 452 | 'media', 453 | 'mews', 454 | 'moose', 455 | 'music', 456 | 'mud', 457 | 'manga', 458 | 'news', 459 | 'only', 460 | 'personnel', 461 | 'pike', 462 | 'plankton', 463 | 'pliers', 464 | 'police', 465 | 'pollution', 466 | 'premises', 467 | 'rain', 468 | 'research', 469 | 'rice', 470 | 'salmon', 471 | 'scissors', 472 | 'series', 473 | 'sewage', 474 | 'shambles', 475 | 'shrimp', 476 | 'software', 477 | 'species', 478 | 'staff', 479 | 'swine', 480 | 'tennis', 481 | 'traffic', 482 | 'transportation', 483 | 'trout', 484 | 'tuna', 485 | 'wealth', 486 | 'welfare', 487 | 'whiting', 488 | 'wildebeest', 489 | 'wildlife', 490 | 'you', 491 | /pok[eé]mon$/i, 492 | // Regexes. 493 | /[^aeiou]ese$/i, // "chinese", "japanese" 494 | /deer$/i, // "deer", "reindeer" 495 | /fish$/i, // "fish", "blowfish", "angelfish" 496 | /measles$/i, 497 | /o[iu]s$/i, // "carnivorous" 498 | /pox$/i, // "chickpox", "smallpox" 499 | /sheep$/i 500 | ].forEach(pluralize.addUncountableRule); 501 | 502 | return pluralize; 503 | }); 504 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "staruml-nestjs", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "lodash.camelcase": { 8 | "version": "4.3.0", 9 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 10 | "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" 11 | }, 12 | "lodash.capitalize": { 13 | "version": "4.2.1", 14 | "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", 15 | "integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=" 16 | }, 17 | "lodash.kebabcase": { 18 | "version": "4.1.1", 19 | "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", 20 | "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=" 21 | }, 22 | "lodash.snakecase": { 23 | "version": "4.1.1", 24 | "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", 25 | "integrity": "sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=" 26 | }, 27 | "pluralize": { 28 | "version": "8.0.0", 29 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", 30 | "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "staruml-nestjs", 3 | "title": "NestJS CRUD", 4 | "description": "Generate nestjsx/crud and nestjs/swagger server based on the class diagrams drawn for entities.", 5 | "homepage": "https://github.com/nestfarm/staruml-nestjs", 6 | "issues": "https://github.com/nestfarm/staruml-nestjs/issues", 7 | "keywords": [ 8 | "NestJS", 9 | "CRUD" 10 | ], 11 | "version": "1.0.0", 12 | "main": "main.js", 13 | "scripts": { 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "author": { 17 | "name": "Jeff Jianfeng Jin", 18 | "email": "jeff.jianfeng.jin@gmail.com", 19 | "url": "https://github.com/inksword" 20 | }, 21 | "license": "MIT", 22 | "engines": { 23 | "staruml": ">=3.0.0" 24 | }, 25 | "dependencies": { 26 | "lodash.camelcase": "^4.3.0", 27 | "lodash.capitalize": "^4.2.1", 28 | "lodash.kebabcase": "^4.1.1", 29 | "lodash.snakecase": "^4.1.1", 30 | "pluralize": "^8.0.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /preferences/preference.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "nest", 3 | "name": "Nest", 4 | "schema": { 5 | "nest.gen": { 6 | "text": "Java Code Generation", 7 | "type": "section" 8 | }, 9 | "nest.gen.javaDoc": { 10 | "text": "JavaDoc", 11 | "description": "Generate JavaDoc comments.", 12 | "type": "check", 13 | "default": true 14 | }, 15 | "nest.gen.useTab": { 16 | "text": "Use Tab", 17 | "description": "Use Tab for indentation instead of spaces.", 18 | "type": "check", 19 | "default": false 20 | }, 21 | "nest.gen.indentSpaces": { 22 | "text": "Indent Spaces", 23 | "description": "Number of spaces for indentation.", 24 | "type": "number", 25 | "default": 4 26 | }, 27 | "nest.gen.tablePrefix": { 28 | "text": "Table Prefix", 29 | "description": "Table prefix for entities.", 30 | "type": "string", 31 | "default": null 32 | } 33 | } 34 | } --------------------------------------------------------------------------------