├── .github ├── .golangci.yml ├── FUNDING.yml └── workflows │ ├── build.yml │ ├── verify-all-committed.yml │ └── verify-templates.yml ├── LICENSE ├── cli ├── cli.go └── cli_test.go ├── codegen ├── codegen.go └── codegen_test.go ├── docs ├── CNAME ├── README.md ├── README_by.md ├── README_es.md ├── README_fr.md ├── README_he.md ├── README_id.md ├── README_jp.md ├── README_ko.md ├── README_pt-br.md ├── README_tr.md ├── README_ua.md ├── README_zh.md ├── _config.yml ├── _includes │ ├── footer.html │ ├── head.html │ └── header.html ├── android-chrome-192x192.png ├── apple-touch-icon.png ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── flag-by.svg ├── logo.svg └── showcase.gif ├── go.mod ├── main.go ├── static └── generated.go ├── templates ├── .dockerignore ├── .gitignore ├── angular.webapp │ ├── .editorconfig │ ├── .gitignore │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ └── tasks.json │ ├── angular.json │ ├── package.json │ ├── src │ │ ├── app │ │ │ ├── app.component.css │ │ │ ├── app.component.html │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ └── tech │ │ │ │ ├── tech.component.html │ │ │ │ ├── tech.component.ts │ │ │ │ ├── tech.model.ts │ │ │ │ └── tech.service.ts │ │ ├── assets │ │ │ ├── .gitkeep │ │ │ └── logo.svg │ │ ├── environments │ │ │ ├── environment.development.ts │ │ │ └── environment.ts │ │ ├── favico.ico │ │ ├── index.html │ │ ├── main.ts │ │ └── styles.css │ ├── tsconfig.app.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── mongo.Dockerfile ├── mongo.README.md ├── mongo.docker-compose-dev.yml ├── mongo.docker-compose.yml ├── mongo.init-db.js ├── mongo.server │ ├── db │ │ └── db.go │ ├── go.mod │ ├── go.sum │ └── server.go ├── mysql.Dockerfile ├── mysql.README.md ├── mysql.docker-compose-dev.yml ├── mysql.docker-compose.yml ├── mysql.init-db.sql ├── mysql.server │ ├── db │ │ └── db.go │ ├── go.mod │ ├── go.sum │ └── server.go ├── postgres.Dockerfile ├── postgres.README.md ├── postgres.docker-compose-dev.yml ├── postgres.docker-compose.yml ├── postgres.init-db.sql ├── postgres.server │ ├── db │ │ └── db.go │ ├── go.mod │ ├── go.sum │ └── server.go ├── react.webapp │ ├── .env.development │ ├── .env.production │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── Logo.js │ │ ├── index.css │ │ ├── index.js │ │ ├── setupTests.js │ │ └── tech │ │ ├── Tech.css │ │ └── Tech.js ├── server │ ├── model │ │ └── technology.go │ └── web │ │ ├── app.go │ │ └── app_test.go └── vue.webapp │ ├── .env.local │ ├── .env.production │ ├── .eslintrc.cjs │ ├── .vscode │ └── extensions.json │ ├── index.html │ ├── package.json │ ├── public │ └── favicon.ico │ ├── src │ ├── App.vue │ ├── assets │ │ └── logo.svg │ ├── components │ │ └── TechItems.vue │ └── main.js │ └── vite.config.js └── transform ├── go.mod ├── transformer.go └── transformer_test.go /.github/.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | output: 3 | format: tab 4 | issues: 5 | exclude-dirs: 6 | - templates 7 | linters: 8 | disable-all: true 9 | enable: 10 | - bodyclose 11 | - depguard 12 | - dogsled 13 | - dupl 14 | - errcheck 15 | - funlen 16 | - gochecknoinits 17 | - goconst 18 | - gocritic 19 | - gocyclo 20 | - gofmt 21 | - mnd 22 | - goprintffuncname 23 | - gosec 24 | - gosimple 25 | - govet 26 | - ineffassign 27 | - lll 28 | - misspell 29 | - nakedret 30 | - rowserrcheck 31 | - staticcheck 32 | - stylecheck 33 | - typecheck 34 | - unconvert 35 | - unparam 36 | - unused 37 | - whitespace 38 | - gocognit 39 | - godox 40 | - prealloc 41 | linters-settings: 42 | depguard: 43 | rules: 44 | prevent_unmaintained_packages: 45 | list-mode: lax # allow unless explicitely denied 46 | files: 47 | - $all 48 | - "!$test" 49 | allow: 50 | - github.com/Shpota/goxygen 51 | deny: 52 | - pkg: io/ioutil 53 | desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil" 54 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [Shpota] 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: [push, pull_request] 3 | jobs: 4 | 5 | test: 6 | name: Build & Test 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v4 11 | - name: Set up go 1.22 12 | uses: actions/setup-go@v4 13 | with: 14 | go-version: '1.22' 15 | id: go 16 | - name: Build 17 | run: go build . 18 | - name: Test 19 | run: go test -v . ./cli ./codegen 20 | - name: Test Transformer 21 | run: cd transform && go test ./... 22 | - name: Lint 23 | run: | 24 | docker run -v $(pwd):/app -w /app golangci/golangci-lint:v1.61-alpine \ 25 | golangci-lint run --config .github/.golangci.yml cli codegen static . 26 | 27 | build: 28 | name: Build 29 | runs-on: ubuntu-latest 30 | strategy: 31 | fail-fast: false 32 | matrix: 33 | go: [ '1.16', '1.17', '1.18', '1.19', '1.20', '1.21' ] 34 | steps: 35 | - name: Checkout 36 | uses: actions/checkout@v4 37 | - name: Set up Go ${{ matrix.go }} 38 | uses: actions/setup-go@v5 39 | with: 40 | go-version: ${{ matrix.go }} 41 | id: go 42 | - name: Build 43 | run: go build . 44 | -------------------------------------------------------------------------------- /.github/workflows/verify-all-committed.yml: -------------------------------------------------------------------------------- 1 | name: Verify template changes are committed 2 | on: [push] 3 | jobs: 4 | verify: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v4 8 | - uses: actions/setup-go@v5 9 | with: 10 | go-version: '1.23' 11 | - name: Generate and format code 12 | run: | 13 | go generate ./... 14 | go fmt ./... 15 | - name: Check for changes 16 | run: | 17 | if [ -n "$(git status --porcelain)" ]; then 18 | echo "Generated files are not up to date!" 19 | git status 20 | exit 1 21 | fi -------------------------------------------------------------------------------- /.github/workflows/verify-templates.yml: -------------------------------------------------------------------------------- 1 | name: verify-templates 2 | on: 3 | push: 4 | pull_request: 5 | schedule: 6 | - cron: '0 14 * * *' 7 | jobs: 8 | 9 | build: 10 | name: Test generated project 11 | runs-on: ubuntu-latest 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | db: [mongo, mysql, postgres] 16 | frontend: [angular, vue, react] 17 | steps: 18 | - name: Checkout project 19 | uses: actions/checkout@v4 20 | - name: Set up Go 21 | uses: actions/setup-go@v5 22 | with: 23 | go-version: '1.22' 24 | - name: Generate application 25 | run: go run main.go init --db ${{ matrix.db }} --frontend ${{ matrix.frontend }} app 26 | - name: Start the application 27 | run: cd app && docker compose up -d 28 | - name: Check availability of backend 29 | run: timeout 60 bash -c 'until curl -s localhost:8080/api/technologies | grep Go > /dev/null; do sleep 1; done' 30 | - name: Check availability of frontend 31 | run: | 32 | npm i puppeteer 33 | cat > index.js << EOF 34 | const puppeteer = require('puppeteer'); 35 | (async () => { 36 | try { 37 | const browser = await puppeteer.launch({ 38 | headless: "new", 39 | args: ['--no-sandbox', '--disable-setuid-sandbox'] 40 | }); 41 | const page = await browser.newPage(); 42 | await page.goto('http://localhost:8080'); 43 | page.on('console', (message) => { 44 | console.log('Console ' + message.type().toUpperCase() + ': ' + message.text()); 45 | }); 46 | await page.waitForSelector('.technologies', { timeout: 60000 }); 47 | const content = await page.content(); 48 | console.log(content); 49 | await browser.close(); 50 | } catch (error) { 51 | console.error('Error:', error); 52 | throw error; 53 | } 54 | })(); 55 | EOF 56 | node index.js 57 | - name: Stop application 58 | run: cd app && docker compose down 59 | if: always() 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2020] [Oleksandr Shpota] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /cli/cli.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "regexp" 8 | ) 9 | 10 | type flag struct { 11 | name string 12 | options []string 13 | defaultValue string 14 | } 15 | 16 | func (f flag) valid(input string) bool { 17 | for _, val := range f.options { 18 | if input == val { 19 | return true 20 | } 21 | } 22 | return false 23 | } 24 | 25 | func Start(w io.Writer, commands []string, generate func(string, []string)) { 26 | if len(commands) == 1 && commands[0] == "help" { 27 | fmt.Fprintln(w, usage) 28 | return 29 | } 30 | if len(commands) >= 2 && commands[0] == "init" { 31 | projectName := commands[len(commands)-1] 32 | input := commands[1 : len(commands)-1] 33 | values, err := parseFlags(input, flags()) 34 | if err != nil { 35 | fmt.Fprintln(w, "Wrong input: "+err.Error()) 36 | fmt.Fprintln(w, usage) 37 | return 38 | } 39 | validName, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", projectName) 40 | if !validName { 41 | fmt.Fprintln(w, invalidName) 42 | return 43 | } 44 | generate(projectName, values) 45 | return 46 | } 47 | fmt.Fprintln(w, "Wrong input!") 48 | fmt.Fprintln(w, usage) 49 | } 50 | 51 | // Retrieves flag values from user input matching them 52 | // against the flags. Returns a map of flags with 53 | // their values or error in case of invalid input. 54 | func parseFlags(input []string, flags []flag) ([]string, error) { 55 | paramCount := 0 56 | values := make([]string, 0, len(flags)) 57 | for _, fl := range flags { 58 | var value string 59 | for index, val := range input { 60 | if val == fl.name && len(input) > index+1 { 61 | value = input[index+1] 62 | if !fl.valid(value) { 63 | return nil, errors.New(`invalid value of "` + fl.name + `" flag`) 64 | } 65 | } 66 | } 67 | if value == "" { 68 | value = fl.defaultValue 69 | } else { 70 | paramCount += 2 71 | } 72 | values = append(values, value) 73 | } 74 | if paramCount != len(input) { 75 | return nil, errors.New("flag mismatch") 76 | } 77 | return values, nil 78 | } 79 | 80 | func flags() []flag { 81 | return []flag{ 82 | {"--frontend", []string{"angular", "react", "vue"}, "react"}, 83 | {"--db", []string{"mongo", "mysql", "postgres"}, "mongo"}, 84 | } 85 | } 86 | 87 | const usage = `Usage: 88 | 89 | go run github.com/shpota/goxygen init [options] 90 | 91 | Options: 92 | 93 | --frontend Specify the front end framework. Possible ` + 94 | `options are "angular", "react" and "vue". If not specified "react" is used. 95 | --db Specify the database. Possible options are ` + 96 | `"mongo" "mysql" and "postgres". If not specified "mongo" is used.` 97 | 98 | const invalidName = "Project name is not valid. The allowed symbols are " + 99 | "letters, numbers, underscores, and dashes." 100 | -------------------------------------------------------------------------------- /cli/cli_test.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "reflect" 7 | "strings" 8 | "testing" 9 | ) 10 | 11 | func TestStart(t *testing.T) { 12 | w := &bytes.Buffer{} 13 | var pjName string 14 | var techStack []string 15 | generate := func(pj string, tech []string) { 16 | pjName = pj 17 | techStack = tech 18 | } 19 | 20 | Start(w, []string{"init", "--frontend", "vue", "my-app"}, generate) 21 | 22 | if pjName != "my-app" || techStack[0] != "vue" { 23 | t.Error("Generation function function received wrong arguments") 24 | } 25 | if w.String() != "" { 26 | t.Errorf("No output expected but got %v", w.String()) 27 | } 28 | } 29 | 30 | func TestStartGivenHelp(t *testing.T) { 31 | w := &bytes.Buffer{} 32 | 33 | Start(w, []string{"help"}, nil) 34 | 35 | got := strings.TrimRight(w.String(), "\n") 36 | if got != usage { 37 | t.Errorf("Start() = %v, want %v", got, usage) 38 | } 39 | } 40 | 41 | func TestStartGivenWrongArguments(t *testing.T) { 42 | w := &bytes.Buffer{} 43 | 44 | Start(w, []string{"wrong", "arguments"}, nil) 45 | 46 | got := strings.TrimRight(w.String(), "\n") 47 | expected := "Wrong input!\n" + usage 48 | if got != expected { 49 | t.Errorf("Start() = %v, want %v", got, expected) 50 | } 51 | } 52 | 53 | func TestStartGivenWrongNameFormat(t *testing.T) { 54 | w := &bytes.Buffer{} 55 | 56 | Start(w, []string{"init", "name.with.dots"}, nil) 57 | 58 | got := strings.TrimRight(w.String(), "\n") 59 | if got != invalidName { 60 | t.Errorf("Start() = %v, want %v", got, invalidName) 61 | } 62 | } 63 | 64 | func TestParseFlags(t *testing.T) { 65 | flags := []flag{{ 66 | "--frontend", []string{"react", "vue"}, "react", 67 | }} 68 | options := []string{"--frontend", "vue"} 69 | 70 | values, err := parseFlags(options, flags) 71 | 72 | if err != nil { 73 | t.Error("parseFlags must not return an error") 74 | } 75 | if len(values) != 1 && values[0] != "vue" { 76 | t.Error(`parseFlags must return ["vue"]`) 77 | } 78 | } 79 | 80 | func TestParseFlagsGivenSeveralFlags(t *testing.T) { 81 | flags := []flag{ 82 | {"--frontend", []string{"react", "vue"}, "react"}, 83 | {"--db", []string{"mysql", "mongo"}, "mongo"}, 84 | } 85 | options := []string{"--frontend", "vue", "--db", "mysql"} 86 | 87 | got, err := parseFlags(options, flags) 88 | 89 | if err != nil { 90 | t.Error("parseFlags must not return an error") 91 | } 92 | exp := []string{"vue", "mysql"} 93 | if !reflect.DeepEqual(got, exp) { 94 | t.Error(`parseFlags must return "vue" and "mysql"`) 95 | } 96 | } 97 | 98 | func TestParseFlagsGivenDefaultValues(t *testing.T) { 99 | flags := []flag{{ 100 | "--frontend", []string{"react", "vue"}, "react", 101 | }} 102 | 103 | got, err := parseFlags([]string{}, flags) 104 | 105 | if err != nil { 106 | t.Error("parseFlags must not return an error") 107 | } 108 | exp := []string{"react"} 109 | if !reflect.DeepEqual(got, exp) { 110 | t.Error(`parseFlags must return "react"`) 111 | } 112 | } 113 | 114 | func TestParseFlagsGivenUnknownArguments(t *testing.T) { 115 | flags := []flag{{ 116 | "--frontend", []string{"react", "vue"}, "react", 117 | }} 118 | options := []string{"--unknown", "test"} 119 | 120 | got, err := parseFlags(options, flags) 121 | 122 | if !reflect.DeepEqual(err, errors.New("flag mismatch")) { 123 | t.Error("parseFlags must return an error") 124 | } 125 | if got != nil { 126 | t.Error("parseFlags must return nil values") 127 | } 128 | } 129 | 130 | func TestParseFlagsGivenWrongFlagValue(t *testing.T) { 131 | flags := []flag{{ 132 | "--frontend", []string{"react", "vue"}, "react", 133 | }} 134 | options := []string{"--frontend", "unknown"} 135 | 136 | values, err := parseFlags(options, flags) 137 | 138 | expected := errors.New(`invalid value of "--frontend" flag`) 139 | if !reflect.DeepEqual(err, expected) { 140 | t.Error("parseFlags must return an error") 141 | } 142 | if values != nil { 143 | t.Error("parseFlags must return nil values") 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /codegen/codegen.go: -------------------------------------------------------------------------------- 1 | package codegen 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "os/exec" 8 | "strings" 9 | 10 | "github.com/shpota/goxygen/static" 11 | ) 12 | 13 | type generator struct { 14 | projectName string 15 | techStack []string 16 | } 17 | 18 | func Generate(projectName string, techStack []string) { 19 | g := generator{projectName, techStack} 20 | g.generate() 21 | } 22 | 23 | func (g generator) generate() { 24 | fmt.Println("Generating", g.projectName) 25 | for path, srcText := range static.Sources() { 26 | srcText = strings.ReplaceAll(srcText, "project-name", g.projectName) 27 | binary := []byte(srcText) 28 | g.processFile(path, binary) 29 | } 30 | for path, binary := range static.Images() { 31 | g.processFile(path, binary) 32 | } 33 | err := g.initGitRepo() 34 | if err != nil { 35 | fmt.Println("Failed to setup a Git repository:", err) 36 | } 37 | fmt.Println("Generation completed.") 38 | } 39 | 40 | // Checks if a file with the given path has to be generated, creates 41 | // a directory structure, and a file with the given content. 42 | func (g generator) processFile(path string, content []byte) { 43 | if !g.needed(path) { 44 | return 45 | } 46 | for _, tech := range g.techStack { 47 | path = strings.Replace(path, tech+".", "", 1) 48 | } 49 | pathElements := strings.Split(path, "/") 50 | separator := string(os.PathSeparator) 51 | pathElements = append([]string{g.projectName}, pathElements...) 52 | _ = os.MkdirAll( 53 | strings.Join(pathElements[:len(pathElements)-1], separator), 54 | os.ModePerm, 55 | ) 56 | fmt.Println("creating: " + strings.Join(pathElements, separator)) 57 | const FILEMODE = os.FileMode(0644) 58 | err := os.WriteFile( 59 | strings.Join(pathElements, separator), 60 | content, 61 | FILEMODE, 62 | ) 63 | if err != nil { 64 | log.Fatal(err) 65 | } 66 | } 67 | 68 | func (g generator) initGitRepo() error { 69 | fmt.Println("setting up Git repository") 70 | cmd := exec.Command("git", "init", "-b", "main", ".") 71 | cmd.Dir = g.projectName 72 | err := cmd.Run() 73 | if err != nil { 74 | return err 75 | } 76 | cmd = exec.Command("git", "add", ".") 77 | cmd.Dir = g.projectName 78 | err = cmd.Run() 79 | if err != nil { 80 | return err 81 | } 82 | cmd = exec.Command("git", "commit", "-m", "Initial commit from Goxygen") 83 | cmd.Dir = g.projectName 84 | return cmd.Run() 85 | } 86 | 87 | // Checks if a path is a framework-specific path (starts 88 | // with framework name). Returns true if a path is 89 | // prefixed with the provided framework followed by dot 90 | // or if a path has no prefix. 91 | func (g generator) needed(path string) bool { 92 | if !hasTechPrefix(path) { 93 | return true 94 | } 95 | for _, tech := range g.techStack { 96 | if strings.HasPrefix(path, tech+".") { 97 | return true 98 | } 99 | } 100 | return false 101 | } 102 | 103 | func hasTechPrefix(path string) bool { 104 | for _, tech := range []string{ 105 | "angular", "react", "vue", "mongo", "mysql", "postgres", 106 | } { 107 | if strings.HasPrefix(path, tech+".") { 108 | return true 109 | } 110 | } 111 | return false 112 | } 113 | -------------------------------------------------------------------------------- /codegen/codegen_test.go: -------------------------------------------------------------------------------- 1 | package codegen 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNeeded(t *testing.T) { 8 | g := generator{techStack: []string{"react"}} 9 | 10 | got := g.needed("react.webapp/test.js") 11 | 12 | if !got { 13 | t.Error("Framework specific paths must be needed") 14 | } 15 | } 16 | 17 | func TestNeededGivenGeneralPath(t *testing.T) { 18 | g := generator{techStack: []string{"react"}} 19 | 20 | got := g.needed("server/server.go") 21 | 22 | if !got { 23 | t.Error("General paths must be needed") 24 | } 25 | } 26 | 27 | func TestNeededGivenExcludedPath(t *testing.T) { 28 | g := generator{techStack: []string{"react"}} 29 | 30 | got := g.needed("angular.webapp/test.js") 31 | 32 | if got { 33 | t.Error("Angular files must not be needed for react") 34 | } 35 | } 36 | 37 | func Test_hasTechPrefix(t *testing.T) { 38 | got := hasTechPrefix("mongo.server/go.mod") 39 | 40 | if !got { 41 | t.Errorf("Must recognize prefix") 42 | } 43 | } 44 | 45 | func Test_hasTechPrefix_GeneralPath(t *testing.T) { 46 | got := hasTechPrefix("unknown.server/go.mod") 47 | 48 | if got { 49 | t.Errorf("Must not recognize prefix") 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | goxygen.dev -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Generate a Web project with Go and Angular, React or Vue.** 57 | 58 | Goxygen aims at saving your time while setting up a new project. It 59 | creates a skeleton of an application with all configuration done for 60 | you. You can start implementing your business logic straight away. 61 | Goxygen generates back end Go code, connects it with front end 62 | components, provides a Dockerfile for the application and creates 63 | docker-compose files for convenient run in development and production 64 | environments. 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
Supported Technologies
Front EndAngularReactVue
Back EndGo
DatabaseMongoDBMySQLPostgreSQL
91 | 92 | ## Requirements 93 | 94 | You need to have Go 1.16 or newer on your machine. 95 | 96 | ## How to use 97 | 98 | Run: 99 | 100 | ```go 101 | go run github.com/shpota/goxygen@latest init my-app 102 | ``` 103 | 104 | This generates a project in `my-app` folder. 105 | 106 | By default, it will use React and MongoDB. You can select 107 | a different front end framework and a database using 108 | `--frontend` and `--db` flags. For instance, this command 109 | will create a project with Vue and PostgreSQL: 110 | 111 | ```go 112 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 113 | ``` 114 | 115 | The `--frontend` flag accepts `angular`, `react` and `vue`. 116 | The `--db` flag accepts `mongo`, `mysql` and `postgres`. 117 | 118 | The generated project is ready to run with Docker Compose: 119 | 120 | ```sh 121 | cd my-app 122 | docker compose up 123 | ``` 124 | 125 | After the build is completed, the application is accessible 126 | on http://localhost:8080. 127 | 128 | You can find more details on how to work with the generated 129 | project in its README file. 130 | 131 | ![Showcase](showcase.gif) 132 | 133 | ## Structure of a generated project (React/MongoDB example) 134 | 135 | my-app 136 | ├── server # Go project files 137 | │ ├── db # MongoDB communications 138 | │ ├── model # domain objects 139 | │ ├── web # REST APIs, web server 140 | │ ├── server.go # the starting point of the server 141 | │ └── go.mod # server dependencies 142 | ├── webapp 143 | │ ├── public # icons, static files, and index.html 144 | │ ├── src 145 | │ │ ├── App.js # the main React component 146 | │ │ ├── App.css # App component-specific styles 147 | │ │ ├── index.js # the entry point of the application 148 | │ │ └── index.css # global styles 149 | │ ├── package.json # front end dependencies 150 | │ ├── .env.development # holds API endpoint for dev environment 151 | │ └── .env.production # API endpoint for prod environment 152 | ├── Dockerfile # builds back end and front end together 153 | ├── docker-compose.yml # prod environment deployment descriptor 154 | ├── docker-compose-dev.yml # runs local MongoDB for development needs 155 | ├── init-db.js # creates a MongoDB collection with test data 156 | ├── .dockerignore # specifies files ignored in Docker builds 157 | ├── .gitignore 158 | └── README.md # guide on how to use the generated repo 159 | 160 | Files such as unit tests or sample components are not included here 161 | for simplicity. 162 | 163 | ## Dependencies 164 | 165 | Goxygen generates a basic structure of a project and doesn't force you 166 | to use a specific set of tools. That's why it doesn't bring unneeded 167 | dependencies to your project. It uses only a database driver on the 168 | back end side and [axios](https://github.com/axios/axios) in React 169 | and Vue projects. Angular projects use only Angular specific libraries. 170 | 171 | ## How to contribute 172 | 173 | If you found a bug or have an idea on how to improve the project 174 | [open an issue](https://github.com/Shpota/goxygen/issues) 175 | and we will fix it as soon as possible. You can also propose your 176 | changes via a Pull Request. Fork the repository, make changes, send 177 | us a pull request and we'll review it shortly. We also have a 178 | [Gitter chat](https://gitter.im/goxygen/community) where we discuss 179 | all the changes. 180 | 181 | ## Credits 182 | 183 | Goxygen's logo was created by [Egon Elbre](https://twitter.com/egonelbre). 184 | -------------------------------------------------------------------------------- /docs/README_by.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Goxygen генеруе Web праекты на Go і сучасных SPA фреймворках.** 57 | 58 | Goxygen захавае ваш час пры стварэнні новых дадаткаў. Ён генеруе 59 | базавую структуру Web праекта і дазваляе адразу ж перайсці да 60 | рэалізацыі бізнес логікі без клопатаў аб канфігурацыі. Goxygen 61 | стварае back end код на Go, звязвае яго з front end кампанентамі, 62 | дадае `Dockerfile` і `docker-compose` для зручнага запуску 63 | лакальна і ў production асяроддзі. 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
Падтрымліваюцца тэхналогіі
Front EndAngularReactVue
Back EndGo
База даныхMongoDBMySQLPostgreSQL
90 | 91 | ## Requirements 92 | Вам трэба мець Go 1.16 або навей вэрсію. 93 | 94 | The `GO111MODULE` environment variable has to be set to `auto` 95 | for the generation logic to work. It is a default for Go 96 | versions up to 1.15. For Go 1.16, you need to set it explicitly: 97 | ``` 98 | export GO111MODULE=auto 99 | ``` 100 | 101 | ## Выкарыстанне 102 | 103 | ```go 104 | go run github.com/shpota/goxygen@latest init my-app 105 | ``` 106 | 107 | У выніку будзе згенераваны праект у дырэкторыі `my-app`. 108 | 109 | React і MongoDB выкарыстоўваецца па змаўчанню. Вы 110 | можаце выбраць розныя front end фреймворк і розныя 111 | базу даных з дапамогай `--frontend` і `--db` сцягі. 112 | Напрыклад, гэтая каманда створыць праект з Vue і PostgreSQL: 113 | 114 | ```go 115 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 116 | ``` 117 | 118 | Сцяг `--frontend` прымае `angular`, `react` або ` vue`. 119 | Сцяг `--db` прымае `mongo`, `mysql` або `postgres`. 120 | 121 | Сфарміраваны праект гатовы да запуску з `docker-compose`: 122 | ```sh 123 | cd my-app 124 | docker compose up 125 | ``` 126 | Пасля завяршэння зборкі, дадатак будзе даступны на 127 | http://localhost:8080. 128 | 129 | Больш дэталяў пра дадатак і як з ім працаваць можна знайсці ў 130 | яго README. 131 | 132 | ![Showcase](showcase.gif) 133 | 134 | ## Структура генераванага праекта (прыкладанне на аснове React/MongoDB) 135 | 136 | my-app 137 | ├── server # серверная частка дадатку (Go) 138 | │ ├── db # камунікацыі з MongoDB 139 | │ ├── model # даменныя аб'екты 140 | │ ├── web # REST API і Web сервер 141 | │ ├── server.go # ўваходная кропка сервернага кода 142 | │ └── go.mod # апісанне Go модуля і залежнасці 143 | ├── webapp 144 | │ ├── public # іконкі, статычныя файлы і index.html 145 | │ ├── src 146 | │ │ ├── App.js # галоўны React кампанент 147 | │ │ ├── App.css # стылі галоўнага кампанента 148 | │ │ ├── index.js # ўходная кропка front end дадатку 149 | │ │ └── index.css # глабальныя стылі 150 | │ ├── package.json # front end залежнасці 151 | │ ├── .env.development # API URL для запуску ў development асяроддзі 152 | │ └── .env.production # API URL для запуску ў production асяроддзі 153 | ├── Dockerfile # збірае front end і back end разам 154 | ├── docker-compose.yml # настройкі для запуску ў production асяроддзі 155 | ├── docker-compose-dev.yml # настройкі для запуску лакальнай базы даных 156 | ├── init-db.js # напаўняе базу даных пачатковымі данымі 157 | ├── .dockerignore # вызначае файлы, якія ігнаруюцца ў Docker зборцы 158 | ├── .gitignore 159 | └── README.md # інструкцыя па выкарыстанні праекта 160 | 161 | Юніт тэсты і дэманстрацыйныя кампаненты не ўключаны ў структуру для прастаты. 162 | 163 | ## Залежнасці 164 | 165 | Goxygen генеруе толькі базавая структуру праекта і не навязвае 166 | вам выкарыстанне спецыфічных бібліятэк або утыліт. Згенераваны 167 | праект будзе мець толькі два старонніх залежнасці: драйвер для базы 168 | даных і бібліятэку для асінхронных REST запытаў, 169 | [axios](https://github.com/axios/axios), для праектаў React і Vue. 170 | 171 | ## Як далучыцца да праекта 172 | 173 | Калі вы знайшлі памылку, ці хочаце прапанаваць паляпшэння, 174 | [адкрыйце issue](https://github.com/Shpota/goxygen/issues) і мы з гэтым 175 | разбярэмся. Таксама можаце прапанаваць свае змены 176 | [у нашым Gitter чаце](https://gitter.im/goxygen/community), або 177 | стварыўшы Pull Request. 178 | 179 | ### Падзякі 180 | 181 | Лагатып Goxygen стварыў [Egon Elbre](https://twitter.com/egonelbre). 182 | -------------------------------------------------------------------------------- /docs/README_es.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Genera un proyecto Web con Go y Angular/React/Vue en segundos.** 57 | 58 | Goxygen aspira a salverte tiempo a la hora de crear un nuevo proyecto, 59 | creando el esqueleto de una aplicacion con la configuracion ya generada, 60 | para que puedas comenzar a implementar la logica de tu negocio inmediatamente. 61 | Goxygen genera el backend con Go, lo conecta con los componentes del frontend 62 | y te ofrece los archivos necesarios para que docker componga los entornos de desarrollo y produccion. 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
Supported Technologies
Front EndAngularReactVue
Back EndGo
DatabaseMongoDBMySQLPostgreSQL
89 | 90 | ## Como se usa 91 | 92 | ```go 93 | go run github.com/shpota/goxygen@latest init my-app 94 | ``` 95 | 96 | Este codigo genera un proyecto en el directorio ``my-app``. 97 | 98 | By default, it will use React and MongoDB. You can select 99 | a different front end framework and a database using 100 | `--frontend` and `--db` flags. For instance, this command 101 | will create a project with Vue and PostgreSQL: 102 | 103 | ```go 104 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 105 | ``` 106 | 107 | The `--frontend` flag accepts `angular`, `react` and `vue`. 108 | The `--db` flag accepts `mongo`, `mysql` and `postgres`. 109 | 110 | El proyecto generado se puede correr utilizando `docker-compose`: 111 | ```sh 112 | cd my-app 113 | docker compose up 114 | ``` 115 | 116 | Una vez la construccion se haya completado la aplicacion estara accesible 117 | a traves de http://localhost:8080. 118 | 119 | Puedes encontrar más detalles en como trabajar con el proyecto generado en su archivo README. 120 | 121 | 122 | ![Showcase](showcase.gif) 123 | 124 | ## Estructura de un proyecto generado (Aplicacion basada en React/MongoDB) 125 | 126 | 127 | my-app 128 | ├── server # archivos de GO 129 | │ ├── db # comunicaciones de MongoDB 130 | │ ├── model # objetos de dominio 131 | │ ├── web # REST APIs, web server 132 | │ ├── server.go # el punto de entrada del servidor 133 | │ └── go.mod # Dependencias del servidor 134 | ├── webapp 135 | │ ├── public # iconos, archivos estaticos e index.html 136 | │ ├── src 137 | │ │ ├── App.js # componente principal de React 138 | │ │ ├── App.css # estilos componente-especifico de la App 139 | │ │ ├── index.js # punto de entrada principal de la aplicacion 140 | │ │ └── index.css # estilos globales 141 | │ ├── package.json # dependencias del front end 142 | │ ├── .env.development # contiene endpoint del API para entorno de desarrollo 143 | │ └── .env.production # endpoint de la API para entornos de produccion 144 | ├── Dockerfile # constructor de backend y frontend juntos 145 | ├── docker-compose.yml # descriptor del despliegue para el entorno de produccion 146 | ├── docker-compose-dev.yml # ejecuta MongoDB localmente para necesidad de desarrollo 147 | ├── init-db.js # genera una collecion de MongoDB con informacion de prueba 148 | ├── .dockerignore # especifica archivos a ignorar en la construccion de Docker 149 | ├── .gitignore 150 | └── README.md # guia de como utilizar la repo generada 151 | 152 | No se han incluido archivos como las informacion de prueba o ejemplos de los componentes para simplicar. 153 | 154 | ## Dependencias 155 | 156 | Goxygen genera la estructura basico de uin proyecto y no te obliga a 157 | utilizar ningun set especifico de herramientas. Es por eso que no incluye 158 | dependencias innecesarias, tan solo utiliza database driver en el backend y 159 | [axios](https://github.com/axios/axios) para pryectos de React y Vue. 160 | Proyectos en Angular solo utilizan librerias especificas. 161 | 162 | ## Como contribuir 163 | 164 | Si encuentras algun bug o tiene ideas para mejorar el proyecto 165 | [abre una hilo](https://github.com/Shpota/goxygen/issues) y lo 166 | solucionaremos lo antes posible. Tambien puedes proponer cambios 167 | a traves de pull request. Haz un fork, realiza cambios y mandanos 168 | un pull request y lo revisaremos. Tambien tenemos un 169 | [Gitter chat](https://gitter.im/goxygen/community) donde discutimos los cambios. 170 | 171 | ### Creditos 172 | Goxygen's logo was created by [Egon Elbre](https://twitter.com/egonelbre). 173 | -------------------------------------------------------------------------------- /docs/README_fr.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Générer un projet web avec Go et Angular/React/Vue en quelques secondes.** 57 | 58 | Goxygen vise à vous faire gagner du temps lors de la mise en place d'un nouveau projet. Il 59 | crée un squelette d'application avec une configuration complète par défaut. 60 | Vous pouvez commencer immédiatement à implémenter votre logique métier. 61 | Goxygen génère du code Backend en Go, le connecte aux composants Frontend, fournit un 62 | Dockerfile pour l'application et crée des fichiers Docker-compose pour une exécution pratique 63 | dans des environnements de développement et de production. 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
Technoligies supportées
Front EndAngularReactVue
Back EndGo
Base de donnéesMongoDBMySQLPostgreSQL
90 | 91 | ## Guide d'utilisation 92 | 93 | ```go 94 | go run github.com/shpota/goxygen@latest init my-app 95 | ``` 96 | 97 | Ces commandes génèrent un projet dans le dossier `my-app`. 98 | 99 | Par défaut, React et MongoDB seront utilisés. Vous pouvez 100 | choisir divers frameworks frontend ou bases de données en 101 | utilisant les flags `--frontend` et `--db`. Par exemple, cette 102 | commande va créer un projet avec Vue et PostreSQL: 103 | 104 | ```go 105 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 106 | ``` 107 | 108 | Le flag `--frontend` accepte les valeurs `angular`, `react` and `vue`. 109 | Le flag `--db` accepte les valeurs `mongo`, `mysql` and `postgres`. 110 | 111 | Le projet généré est prêt à l'utilisation avec `docker-compose`: 112 | 113 | ```sh 114 | cd my-app 115 | docker compose up 116 | ``` 117 | 118 | Aprés la fin du build, l'application est 119 | accessible sur http://localhost:8080. 120 | 121 | Vous trouverez plus de détails sur l'utilisation 122 | du projet généré dans son fichier README. 123 | 124 | ![Présentation](showcase.gif) 125 | 126 | ## Structure d'un projet généré (application React/MongoDB) 127 | 128 | my-app 129 | ├── server # fichier du projet Go 130 | │ ├── db # communications avec MongoDB 131 | │ ├── model # objets du domaine 132 | │ ├── web # REST APIs, serveur web 133 | │ ├── server.go # point d'entrée du serveur 134 | │ └── go.mod # dépendances du serveur 135 | ├── webapp 136 | │ ├── public # icones, fichiers statiques, et index.html 137 | │ ├── src 138 | │ │ ├── App.js # le composant React principale 139 | │ │ ├── App.css # style spécifiques au composant App 140 | │ │ ├── index.js # le point d'entrée de l'application 141 | │ │ └── index.css # styles globaux 142 | │ ├── package.json # dépendances du frontend 143 | │ ├── .env.development # endpoint de l'API pour l'environnement de développement 144 | │ └── .env.production # endpoint de l'API pour l'environnement de production 145 | ├── Dockerfile # build du backend et du frontend 146 | ├── docker-compose.yml # description des déploiements dans un environnement de production 147 | ├── docker-compose-dev.yml # lance une instance de MongoDB en local pour développement 148 | ├── init-db.js # crée une collection MongoDB avec des données de test 149 | ├── .dockerignore # spécifie les fichiers ignorés lors des builds docker 150 | ├── .gitignore 151 | └── README.md # guide d'utilisation du projet généré 152 | 153 | Les fichiers de tests unitaires ou d'exemples de composants ne sont pas inclus 154 | pour des raisons de simplicité. 155 | 156 | ## Dépendances 157 | 158 | Goxygen génére un projet avec une structure basique et ne vous force pas à utiliser des 159 | outils spécifiques. C'est pour cela que les seules dépendances utilisées dans le projet 160 | sont database driver côté backend et [axios](https://github.com/axios/axios) côté 161 | frontend les projets React et Vue. Les projets Angular utilisent leurs propres librairies. 162 | 163 | ## Comment contribuer 164 | 165 | Si vous trouvez un bug ou avez une idée sur comment améliorer le projet 166 | [créez une issue](https://github.com/Shpota/goxygen/issues) 167 | et nous corrigerons le problème le plus rapidement possible. Vous pouvez aussi 168 | proposer vos propres changement avec des Pull Request. Faites un Fork du dépôt, 169 | effectuer vos modifications, envoyez-nous un pull request et nous le consulterons dans 170 | les plus brefs délais. Nous disposons aussi d'un [chat Gitter](https://gitter.im/goxygen/community) 171 | où nous discutons tous les changements. 172 | 173 | ### Crédits 174 | 175 | Le logo de Goxygen à été crée par [Egon Elbre](https://twitter.com/egonelbre). 176 | -------------------------------------------------------------------------------- /docs/README_he.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 |
40 | Goxygen 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
54 |

55 | 56 | 57 | goxygen logo 58 | 59 | 60 |
61 | 62 | **יצירה אוטומטית של פרויקט Web באמצעות Go ו-Angular, React או Vue.** 63 | 64 | מטרת Goxygen היא לחסוך זמן במהלך הקמת פרויקט חדש. 65 | הוא מייצר שלד עבור יישום עם כל הקונפיגורציה מוכנה עבורכם. 66 | אתם יכולים ישר להתחיל לממש את ההיגיון העסקי שלכם. 67 | Goxygen מג'נרט back-end בשפת Go, מחבר אותו עם הרכיבים של ה-front-end, מספק Dockerfile עבור היישום ומייצר קבצי docker-compose להפעלה נוחה בסביבות הפיתוח והייצור (production). 68 |
69 | 70 |
71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
טכנולוגיות נתמכות
Front EndAngularReactVue
Back EndGo
בסיס נתוניםMongoDBMySQLPostgreSQL
96 |
97 | 98 |
99 | 100 | ## Requirements 101 | עליכם להתקין Go 1.16 ומעלה במחשב שלכם. 102 | 103 | ## איך להשתמש 104 |
105 | 106 | ```go 107 | go run github.com/shpota/goxygen@latest init my-app 108 | ``` 109 | 110 |
111 | 112 | פקודה זו תייצר פרויקט בתיקיית `my-app`. 113 |
114 | 115 |
116 | 117 | כברירת מחדל, הכלי ישתמש ב-React ו-MongoDB. 118 | אתם יכולים לבחור front-end framework ובסיס נתונים אחרים באמצעות הדגלים `--frontend` ו-`--db` בהתאמה. 119 | למשל פקודה זו תייצר פרויקט מבוסס Vue ו-PostgreSQL: 120 |
121 | 122 | ```go 123 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 124 | ``` 125 | 126 |
127 | 128 | דגל `--frontend` תומך באפשרויות `angular`, `react` ו-`vue`. 129 | דגל `--db` תומך באפשרויות `mongo`, `mysql` ו-`postgres`. 130 |
131 | 132 |
133 | 134 | הפרויקט שנוצר מוכן להפעלה עם `docker-compose`: 135 |
136 | 137 | ```sh 138 | cd my-app 139 | docker compose up 140 | ``` 141 | 142 |
143 | 144 | אחרי שה-build הסתיים, היישום נגיש ב-http://localhost:8080. 145 |
146 | 147 |
148 | 149 | אתם יכולים למצוא פרטים נוספים על איך לעבוד עם הפרויקט שנוצר בקובץ ה-README שלו. 150 |
151 | 152 | ![Showcase](showcase.gif) 153 | 154 |
155 | 156 | ## מבנה של פרויקט שג'ונרט (דוגמת React/MongoDB) 157 |
158 | 159 | 160 | my-app 161 | ├── server # Go קבצי פרויקט 162 | │ ├── db # MongoDB תקשורת 163 | │ ├── model # domain אובייקטי 164 | │ ├── web # REST APIs, web שרת 165 | │ ├── server.go # נקודת ההתחלה של השרת 166 | │ └── go.mod # של השרת dependencies 167 | ├── webapp 168 | │ ├── public # index.html-אייקונים, קבצים סטטיים ו 169 | │ ├── src 170 | │ │ ├── App.js # React הרכיב המרכזי של 171 | │ │ ├── App.css # App סגנונות ספציפיים עבור רכיב 172 | │ │ ├── index.js # נקודת הכניסה של היישום 173 | │ │ └── index.css # סגנונות גלובליים 174 | │ ├── package.json # front end-של ה dependencies 175 | │ ├── .env.development # dev-לסביבת ה API-מחזיק בנקודת הקצה של ה 176 | │ └── .env.production # prod-לסביבת ה API-מחזיק בנקודת הקצה של ה 177 | ├── Dockerfile # ביחד front end-וה back end-של ה build 178 | ├── docker-compose.yml # prod תיאור פריסת סביבת 179 | ├── docker-compose-dev.yml # מקומי לצרכי פיתוח MongoDB מפעיל 180 | ├── init-db.js # עם נתוני בדיקה MongoDB-יוצר אסופה ב 181 | ├── .dockerignore # Docker builds מציין קבצים שיש להתעלם מהם בעת 182 | ├── .gitignore 183 | └── README.md # שנוצר repo-מדריך כיצד להשתמש ב 184 | 185 |
186 | 187 | קבצים כמו קבצי unit tests או רכיבי בסיס אינם כלולים כאן לצורך פשטות. 188 |
189 | 190 |
191 | 192 | ## תלויות - Dependencies 193 |
194 | 195 |
196 | 197 | Goxygen מג'נרט שלד בסיסי של פרויקט ואינו מכריח אתכם להשתמש בקבוצת כלים מסוימת. לכן, הוא לא מוסיף תלויות בלתי נחוצות לפרויקט שלכם. 198 | הוא משתמש רק ב-driver עבור בסיס נתונים ב-back end וב-[axios](https://github.com/axios/axios) בפרויקטים מבוססי React או Vue. בפרויקטים מבוססי Angular הוא משתמש רק בספריות ספציפיות של Angular. 199 |
200 | 201 |
202 | 203 | ## איך לתרום 204 |
205 | 206 |
207 | 208 | אם מצאתם באג או שיש לכם רעיון כיצד לשפר את הפרויקט [open an issue](https://github.com/Shpota/goxygen/issues) ואנחנו נתקן אותו בהקדם האפשרי. אתם יכולים גם להציע שינויים באמצעות Pull Request. תעשו Fork ל-repository, בצעו שינויים, שלחו לנו בקשת pull ואנחנו נבדוק אותה בקרוב. יש לנו גם [Gitter chat](https://gitter.im/goxygen/community) בו אנו דנים בכל השינויים. 209 |
210 | 211 |
212 | 213 | ### קרדיטים 214 |
215 | 216 |
217 | 218 | הלוגו של Goxygen נוצר על ידי [Egon Elbre](https://twitter.com/egonelbre). 219 |
220 | -------------------------------------------------------------------------------- /docs/README_id.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Menyiapkan web projek menggunakan Go dan Angular/React/Vue.** 57 | 58 | Goxygen bertujuan untuk menghemat waktu Anda dalam menyiapkan 59 | sebuah proyek web baru.Goxygen menciptakan kerangka aplikasi 60 | dengan semua konfigurasi yang telah disiapkan untuk Anda. Jadi 61 | Anda dapat langsung segera memulai menerapkan logika bisnis 62 | pada proyek Anda. Goxygen menghasilkan kode Go yang berfungsi 63 | sebagai back-end, menghubungkannya dengan komponen front-end, 64 | menyediakan Dockerfile untuk aplikasi docker dan membuat file 65 | docker-compose agar mudah dijalankan dalam fase pengembangan 66 | dan fase produksi. 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |
Supported Technologies
Front EndAngularReactVue
Back EndGo
DatabaseMongoDBMySQLPostgreSQL
93 | 94 | ## Requirements 95 | Anda harus mempunyai Go versi 1.16 atau yang lebih pada mesin Anda. 96 | 97 | 98 | ## Cara penggunaan 99 | 100 | ```go 101 | go run github.com/shpota/goxygen@latest init my-app 102 | ``` 103 | 104 | Ini akan meng-generate sebuah projek di dalam `my-app` folder. 105 | 106 | By default, it will use React and MongoDB. You can select 107 | a different front end framework and a database using 108 | `--frontend` and `--db` flags. For instance, this command 109 | will create a project with Vue and PostgreSQL: 110 | 111 | ```go 112 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 113 | ``` 114 | 115 | The `--frontend` flag accepts `angular`, `react` and `vue`. 116 | The `--db` flag accepts `mongo`, `mysql` and `postgres`. 117 | 118 | Proyek yang telah di generate dapat dijalankan dengan perintah `docker-compose`: 119 | ```sh 120 | cd my-app 121 | docker compose up 122 | ``` 123 | Setelah proses build selesai, aplikasi dapat diakses 124 | pada http://localhost:8080. 125 | 126 | Anda dapat menemukan detail lebih lanjut tentang bagaimana cara bekerja 127 | dengan proyek dengan membuka file README. 128 | 129 | ![Showcase](showcase.gif) 130 | 131 | ## Struktur proyek yang dihasilkan (React-based app) 132 | 133 | my-app 134 | ├── server # Proyek file go 135 | │ ├── db # Komunikasi dengan MongoDB 136 | │ ├── model # domain objek 137 | │ ├── web # REST APIs, web server 138 | │ ├── server.go # titik awal dari server 139 | │ └── go.mod # server dependensi 140 | ├── webapp 141 | │ ├── public # icons, static file, dan index.html 142 | │ ├── src 143 | │ │ ├── App.js # titik awal komponen React 144 | │ │ ├── App.css # App component-specific style 145 | │ │ ├── index.js # titik awal dari the application 146 | │ │ └── index.css # style global 147 | │ ├── package.json # front end dependensi 148 | │ ├── .env.development # memegang API endpoint untuk fase pengembangan 149 | │ └── .env.production # API endpoint untuk fase produksi 150 | ├── Dockerfile # membangun back end dan front-end secara bersamaan 151 | ├── docker-compose.yml # prod environemnt deployment deskriptor 152 | ├── docker-compose-dev.yml # menjalankan local MongoDB untuk kepentingan pengembangan 153 | ├── init-db.js # membuat koleksi MongoDB dengan data uji 154 | ├── .dockerignore # menentukan file yang diabaikan dalam pembuatan Docker 155 | ├── .gitignore 156 | └── README.md # panduan tentang cara menggunakan repo yang dihasilkan 157 | 158 | File seperti unit test atau komponen sampel tidak termasuk di sini 159 | untuk kesederhanaan. 160 | 161 | ## Dependensi 162 | 163 | Goxygen menghasilkan struktur dasar suatu proyek dan tidak memaksa Anda 164 | untuk menggunakan seperangkat alat tertentu. Itu sebabnya Goxygen tidak 165 | membawa dependensi yang tidak dibutuhkan pada proyek Anda. Hanya menggunakan 166 | database driver pada back end side dan [axios](https://github.com/axios/axios) 167 | pada projek React dan Vue. Angular proyek hanya menggunakan Angular library 168 | tertentu. 169 | 170 | ## Bagaimana cara berkontribusi 171 | 172 | Jika Anda menemukan bug atau punya ide tentang cara meningkatkan proyek 173 | [open an issue](https://github.com/Shpota/goxygen/issues) 174 | dan kami akan memperbaikinya sesegera mungkin. Anda juga dapat mengusulkan 175 | perubahan melalui Pull Request. Fork repositori, buat perubahan, dan kirim 176 | kami pull request dan kami akan segera memeriksanya. Kami juga punya 177 | [Gitter chat](https://gitter.im/goxygen/community) dimana kita bahas 178 | semua perubahan. 179 | 180 | ### Penghargaan 181 | Goxygen's logo dibuat oleh [Egon Elbre](https://twitter.com/egonelbre). 182 | -------------------------------------------------------------------------------- /docs/README_jp.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Go、Angular / React / Vue を用いた Web プロジェクトを生成します。** 57 | 58 | Goxygen は、新しいプロジェクトを始める際の時間の節約を目的としており、すべての 59 | 設定が済まされたアプリケーションの雛形を作成します。ビジネスロジックの実装をす 60 | ぐに開始できます。Goxygen はバックエンドの Go 言語のコードを生成し、それをフロ 61 | ントエンドコンポーネントと関連づけます。加えて、アプリケーション用の Dockerfile 62 | を提供し、開発および本番環境での実行に便利な docker-compose ファイルを作成しま 63 | す。 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
対応技術
フロントエンドAngularReactVue
バックエンドGo
データベースMongoDBMySQLPostgreSQL
90 | 91 | ## Requirements 92 | Go 1.16 以上が必要です。 93 | 94 | ## 使用方法 95 | ```go 96 | go run github.com/shpota/goxygen@latest init my-app 97 | ``` 98 | `my-app` プロジェクトを `my-app` フォルダに生成します。 99 | 100 | デフォルトでは、React 及び MongoDB を使用します。 101 | `--frontend` と `--db` フラグを使って異なる 102 | フロントエンドフレームワークとデータベースを選べます。 103 | 例えば、次のコマンドは Vue と PostgreSQL を含むプロジェクト作成します: 104 | 105 | ```go 106 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 107 | ``` 108 | 109 | `--frontend` フラグは、`angular` や `react`、`vue` を受け取ります。 110 | `--db` フラグは、`mongo` や `mysql`、`postgres` を受け取ります。 111 | 112 | 生成されたプロジェクトは、`docker-compse` で実行する準備が整っています: 113 | ```sh 114 | cd my-app 115 | docker compose up 116 | ``` 117 | ビルドが完了後、アプリケーションは http://localhost:8080 でアクセスできるように 118 | なります。 119 | 120 | 生成されたプロジェクトの操作方法に関する詳細については、READMEファイルを参照し 121 | てください。 122 | 123 | ![Showcase](showcase.gif) 124 | 125 | ## 生成されるプロジェクトの構造 (React/MongoDBベースアプリケーション) 126 | 127 | my-app 128 | ├── server # Go プロジェクトファイル 129 | │ ├── db # MongoDB との通信 130 | │ ├── model # ドメインオブジェクト 131 | │ ├── web # REST APIs, web サーバ 132 | │ ├── server.go # サーバの開始点 133 | │ └── go.mod # サーバ依存関係 134 | ├── webapp 135 | │ ├── public # アイコン、静的ファイル、index.html 136 | │ ├── src 137 | │ │ ├── App.js # 主要な React コンポーネント 138 | │ │ ├── App.css # アプリコンポーネント固有のスタイル 139 | │ │ ├── index.js # アプリケーションのエントリポイント 140 | │ │ └── index.css # 全体のスタイル 141 | │ ├── package.json # フロントエンド依存関係 142 | │ ├── .env.development # 開発環境の API エンドポイント保持 143 | │ └── .env.production # プロダクション環境の API エンドポイント 144 | ├── Dockerfile # バックエンド・フロントエンドを共に構築します 145 | ├── docker-compose.yml # プロダクション環境の配置記述 146 | ├── docker-compose-dev.yml # 開発に必要なローカルの MongoDB を実行する 147 | ├── init-db.js # テストデータで MongoDB コレクションを作成します 148 | ├── .dockerignore # Docker のビルドで無視するファイルを指定します 149 | ├── .gitignore 150 | └── README.md # 生成したリポジトリの使用方法に関するガイド 151 | 152 | 単純にするため、ここには単体テストやサンプルコンポーネントなどのファイルは含ま 153 | れていません。 154 | 155 | ## 依存関係 156 | 157 | Goxygen は、プロジェクトの基本的な構造を生成し、特定のツール群を使用するように 158 | 強制しません。それが、プロジェクトに不要な依存関係をもたらさない理由です。バッ 159 | クエンド側では database driver を、 160 | React 及び Vue プロジェクトでは、[axios](https://github.com/axios/axios) のみを 161 | 使用します。Angular プロジェクトでは、Angular 固有のライブラリのみを使用します。 162 | 163 | ## 貢献の仕方 164 | 165 | バグを発見した場合、またはプロジェクトを改善する方法についてアイディアがある場 166 | 合 [open an issue](https://github.com/Shpota/goxygen/issues)、できるだけ早く修 167 | 正します。Pull Request を通して変更を提案することもできます。リポジトリを Fork 168 | し、変更を加え、Pull Request を送信してください。すぐに確認をします。また、あら 169 | ゆる変更点について話し合う [Gitter chat](https://gitter.im/goxygen/community) 170 | もあります。 171 | 172 | ### クレジット 173 | Goxygen のロゴは、[Egon Elbre](https://twitter.com/egonelbre) によって作成され 174 | ました。 175 | -------------------------------------------------------------------------------- /docs/README_ko.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **순식간에 GO 그리고 Angular/React/Vue 를 활용한 웹 프로젝트를 생성해보세요** 57 | Goxygen은 사용자가 새로운 프로젝트를 설정하는데 필요한 시간을 아끼는데 중점을 두고있습니다. 58 | 사용자를 위한 모든 설정을 포함한 어플리케이션의 뼈대를 생성합니다. 사용자는 생각했던 59 | 비지니스 로직을 즉시 행동으로 옮길 수 있습니다. Goxygen 은 Go 코드로 벡엔드를 생성하고, 60 | 그것을 프론트엔드 요소들에 연결 시킨 후, 어플리케이션을 위한 Dockerfile 을 제공하면서 61 | 개발과 제작 환경에서 간단한 실행을 위한 docker-compose 파일을 만듭니다. 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
Supported Technologies
Front EndAngularReactVue
Back EndGo
DatabaseMongoDBMySQLPostgreSQL
88 | 89 | ## Requirements 90 | 사용자는 Go 1.16 또는 그 이상의 버젼이 필요합니다. 91 | 92 | ## 사용하는 방법 93 | ```go 94 | go run github.com/shpota/goxygen@latest init my-app 95 | ``` 96 | `my-app` 폴더에 프로젝트를 생성합니다. 97 | 98 | 기본설정으로 React 와 MongoDB를 사용합니다. 99 | 다른 프런트엔드 프레임워크와 데이터베이스를 선택하고 싶다면 `--frontend`와 `--db` 플래그를 사용합니다. 예를 들어 아래의 명령은 Vue와 PostgreSQL을 사용하여 프로젝트를 생성합니다: 100 | 101 | ```go 102 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 103 | ``` 104 | 105 | The `--frontend` flag accepts `angular`, `react` and `vue`. 106 | The `--db` flag accepts `mongo`, `mysql` and `postgres`. 107 | 108 | 생성된 프로젝트는 `docker-compose`를 통해 실행 될 수 있습니다. 109 | ```sh 110 | cd my-app 111 | docker compose up 112 | ``` 113 | 빌드가 끝나면, 어플리케이션은 http://localhost:8080에서 연결이 114 | 가능합니다. 115 | 116 | 사용자는 프로젝트의 README 파일에서 더 자세한 사항을 알아볼 수 있습니다 117 | 118 | ![Showcase](showcase.gif) 119 | 120 | ## 생성된 프로젝트의 구조 (React/MongoDB 기반 앱) 121 | 122 | my-app 123 | ├── server # Go 프로젝트 파일 124 | │ ├── db # MongoDB 연결 125 | │ ├── model # domain objects 126 | │ ├── web # REST APIs, web server 127 | │ ├── server.go # 서버의 시작점 128 | │ └── go.mod # server 필수 요소 129 | ├── webapp 130 | │ ├── public # icons, static 파일, 그리고 index.html 131 | │ ├── src 132 | │ │ ├── App.js # 주 React 요소 133 | │ │ ├── App.css # App 요소 중점의 스타일(styles) 134 | │ │ ├── index.js # application의 시작 기점 135 | │ │ └── index.css # global 스타일(styles) 136 | │ ├── package.json # front end 필수 요소 137 | │ ├── .env.development # 개발환경의 API endpoint 138 | │ └── .env.production # 제작환경의 API endpoint 139 | ├── Dockerfile # 벡엔드와 프론트엔드를 함께 빌드 140 | ├── docker-compose.yml # 제작환경 배포 설명서 141 | ├── docker-compose-dev.yml # 개발에 필요한 로컬 MongoDB를 실행 142 | ├── init-db.js # 테스트 data 로 MongoDB 컬렉션 생성 143 | ├── .dockerignore # Docker 빌드에서 무시할 파일 설정 144 | ├── .gitignore 145 | └── README.md # 생성된 레포지토리 사용 가이드 146 | 147 | 간략함을 위해 유닛 테스트나 샘플요소는 추가되지 않았습니다. 148 | 149 | ## 필수요소(dependencies) 150 | Goxygen 프로젝트의 기본적인 구조만을 생성하며 사용자가 구체적인 도구(tool)를 151 | 사용하라고 강요하지 않습니다. 프로젝트에 필요없는 필수요소(dependency)를 152 | 가져오지 않는 이유가 여기에 있습니다. 벡엔드에는 오직 153 | database driver을 사용하며 154 | React나 Vue 프로젝트에선 [axios](https://github.com/axios/axios) 만을 사용합니다. 155 | Angular 프로젝트는 오직 Angular 특화된 라이브러리만을 사용합니다. 156 | 157 | 158 | ## 기여하는 방법 159 | 160 | 만약 버그를 찾았더라던가 이 프로젝트를 더 나은 방향으로 인도할 수 있는 161 | 아이디어를 갖고 있다면 162 | [이슈를 열어주세요](https://github.com/Shpota/goxygen/issues) 163 | 그리고 빠른 시일내에 조치하겠습니다. Pull Request를 통해 변경사항을 제안할 수 164 | 있습니다. 레포지토리를 Fork하고 더 좋은 방향으로 변경하고 Pull Request 를 165 | 저희에게 보내주세요. 짧은 시일내로 반영하겠습니다. 또한 저희는 166 | [Gitter chat](https://gitter.im/goxygen/community) 에서 모든 사항을 167 | 공유 중 입니다. 168 | 169 | ### 크레딧 170 | Goxygen 로고는 [Egon Elbre](https://twitter.com/egonelbre) 에 의해 만들어 졌습니다. 171 | -------------------------------------------------------------------------------- /docs/README_pt-br.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Crie um projeto Web com Go e Angular/React/Vue em segundos.** 57 | 58 | Goxygen visa poupar seu tempo ao montar um novo projeto. Ele 59 | cria o esqueleto de uma aplicação com todas as configurações 60 | prontas para você. Você pode começar a implementar sua lógica 61 | de negócios imediatamente. Goxygen gera o código back end em Go, 62 | conecta ele com os componentes front end, fornece o Dockerfile 63 | para a aplicação e cria o arquivo docker-compose para rapidamente 64 | executar em ambientes de desenvolvimento e produção. 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
Tecnologias suportadas
Front EndAngularReactVue
Back EndGo
DatabaseMongoDBMySQLPostgreSQL
91 | 92 | ## Requisitos 93 | Você precisa de Go 1.16 ou mais recente na sua máquina. 94 | 95 | ## Como utilizar 96 | 97 | ```go 98 | go run github.com/shpota/goxygen@latest init my-app 99 | ``` 100 | 101 | Isso gera um projeto no diretório `my-app`. 102 | 103 | Por padrão, será usado React e MongoDB. Você pode selecionar 104 | um framework de front end e um banco de dados diferentes usando 105 | os argumentos `--frontend` e `--db`. Por exemplo, este comando 106 | criará um projeto usando Vue e PostgreSQL: 107 | 108 | ```go 109 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 110 | ``` 111 | 112 | O argumento `--frontend` aceita as opções `angular`, `react` e `vue`. 113 | O argumento `--db` aceita as opções `mongo`, `mysql` e `postgres`. 114 | 115 | O projeto gerado está pronto para ser executado com `docker-compose`: 116 | ```sh 117 | cd my-app 118 | docker compose up 119 | ``` 120 | 121 | Após o build ser concluído, a aplicação ficará disponível em 122 | http://localhost:8080. 123 | 124 | Você pode encontrar mais detalhes de como utilizar o projeto 125 | gerado em seu arquivo README. 126 | 127 | ![Showcase](showcase.gif) 128 | 129 | ## Estrutura do projeto gerado (Exemplo com React/MongoDB) 130 | 131 | my-app 132 | ├── server # Arquivos do projeto Go 133 | │ ├── db # Comunicação com o MongoDB 134 | │ ├── model # Objetos de domínio 135 | │ ├── web # REST APIs, servidor web 136 | │ ├── server.go # O ponto de acesso do servidor 137 | │ └── go.mod # dependências do servidor 138 | ├── webapp 139 | │ ├── public # ícones, arquivos estáticos e index.html 140 | │ ├── src 141 | │ │ ├── App.js # O principal componente React 142 | │ │ ├── App.css # Estilização do componente App 143 | │ │ ├── index.js # Ponto de entrada da aplicação 144 | │ │ └── index.css # Estilos globais 145 | │ ├── package.json # dependências do front end 146 | │ ├── .env.development # API endpoint para ambiente de desenvolvimento 147 | │ └── .env.production # API endpoint para ambiente de produção 148 | ├── Dockerfile # faz o build do back end e o front end juntos 149 | ├── docker-compose.yml # deploy em ambiente de produção 150 | ├── docker-compose-dev.yml # executa um MongoDB local para fins de desenvolvimento 151 | ├── init-db.js # cria um MongoDB collection com dados de teste 152 | ├── .dockerignore # especifica arquivos ignorados no Docker build 153 | ├── .gitignore 154 | └── README.md # guia sobre como usar o repositório gerado 155 | 156 | Arquivos como testes unitários ou componentes de exemplo não estão incluídos 157 | aqui para fins de simplicidade. 158 | 159 | ## Dependências 160 | 161 | Goxygen gera uma estrutura básica de um projeto e não o força usar um 162 | conjunto específico de ferramentas. E por isso não traz dependências 163 | desnecessárias para o seu projeto. Ele usa apenas 164 | um driver de banco de dados no back end 165 | e [axios](https://github.com/axios/axios) nos projetos React e Vue. 166 | Projetos Angular usam apenas bibliotecas específicas do Angular. 167 | 168 | ## Como contribuir 169 | 170 | Se você encontrou um bug ou tem alguma ideia de como melhorar o projeto, 171 | [abra um issue](https://github.com/Shpota/goxygen/issues) 172 | e nós iremos consertar o mais rápido possível. Você também pode enviar 173 | suas alterações via Pull Request. Dê um fork no repositório, faça 174 | alterações, nos envie um pull request que nós iremos analisar em breve. 175 | Nós também temos um 176 | [Gitter chat](https://gitter.im/goxygen/community) onde discutimos todas 177 | as alterações. 178 | 179 | ### Créditos 180 | O logo do Goxygen foi criado por [Egon Elbre](https://twitter.com/egonelbre). 181 | -------------------------------------------------------------------------------- /docs/README_tr.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Go ve Angular, React veya Vue ile bir web projesi oluşturun.** 57 | 58 | Goxygen, yeni bir proje oluştururken sizin zamandan tasarruf etmenize odaklanır. Sizin için bütün konfigürasyonları yapılmış bir uygulama iskeleti oluşturur. İş mantığınızı hemen uygulamaya başlayabilirsiniz. Goxygen, back-end Go kodu oluşturur, front-end tarafında componentlere bağlar, uygulama için bir Dockerfile sağlar ve production ortamında rahat çalışma için docker-compose dosyalarını oluşturur. 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
Desteklenen Teknolojiler
Front EndAngularReactVue
Back EndGo
DatabaseMongoDBMySQLPostgreSQL
85 | 86 | ## Gereksinimler 87 | 88 | Makinenizde Go 1.16 veya daha yenisine sahip olmanız gerekmektedir. 89 | 90 | ## Nasıl Kullanılır 91 | 92 | Çalıştır: 93 | 94 | ```go 95 | go run github.com/shpota/goxygen@latest init my-app 96 | ``` 97 | 98 | `my-app` klasöründe bir proje oluşturur. 99 | 100 | Varsayılan olarak React ve MongoDB'yi kullanacaktır. Farklı bir front-end framework'ü ve veritabanını `--frontend` ve `--db` flag'lerini kullanarak seçebilirsin. Örneğin bu komut Vue ve PostgreSQL ile bir proje oluşturacaktır: 101 | 102 | ```go 103 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 104 | ``` 105 | 106 | `--frontend` flag'i `angular`, `react` ve `vue` değerlerini kabul eder. 107 | `--db` flag'i `mongo`, `mysql` ve `postgres` değerlerini kabul eder. 108 | 109 | Oluşturulan proje `docker-compose` komutu ile çalıştırmaya hazır olacaktır: 110 | 111 | ```sh 112 | cd my-app 113 | docker compose up 114 | ``` 115 | 116 | Build tamamlandıktan sonra, uygulama http://localhost:8080 adresinden erişilebilir olacaktır. 117 | 118 | Oluşturulan projeyle nasıl çalışılacağı hakkında daha fazla ayrıntıyı README dosyasında bulabilirsiniz. 119 | 120 | ![Showcase](showcase.gif) 121 | 122 | ## Oluşturulmuş bir projenin yapısı (Örnek: React/MongoDB) 123 | 124 | my-app 125 | ├── server # Go proje dosyaları 126 | │ ├── db # MongoDB iletişimleri 127 | │ ├── model # domain nesneleri 128 | │ ├── web # REST APIs, web server 129 | │ ├── server.go # Sunucunun başlama noktası 130 | │ └── go.mod # Sunucu bağımlılıkları 131 | ├── webapp 132 | │ ├── public # ikonlar, sabit dosyalar, ve index.html 133 | │ ├── src 134 | │ │ ├── App.js # Ana React komponenti 135 | │ │ ├── App.css # Uygulama bileşenine özgü stiller 136 | │ │ ├── index.js # Uygulamanın giriş noktası 137 | │ │ └── index.css # global stiller 138 | │ ├── package.json # front end bağımlılıkları 139 | │ ├── .env.development # Geliştirme ortamı için API Endpointlerini barındırır. 140 | │ └── .env.production # Production ortamı için API endpoint'leri 141 | ├── Dockerfile # Back-end ve front-end'i birlikte oluşturur. 142 | ├── docker-compose.yml # Üretim ortamı dağıtım tanımlayıcısı 143 | ├── docker-compose-dev.yml # Geliştirme ihtiyaçları için yerel MongoDB çalıştırır. 144 | ├── init-db.js # Test verileriyle bir MongoDB koleksiyonu oluşturur. 145 | ├── .dockerignore # Docker yapılarında yok sayılan dosyaları belirtir. 146 | ├── .gitignore 147 | └── README.md # Oluşturulan repo'nun nasıl kullanılacağına dair kılavuz. 148 | 149 | Birim testleri veya örnek komponentler gibi dosyalar, basitlik açısından buraya dahil edilmemiştir. 150 | 151 | ## Bağımlılıklar 152 | 153 | Goxygen, bir projenin temel yapısını oluşturur ve sizi belirli bir takım araçları kullanmaya zorlamaz. Bu yüzden projenize gereksiz bağımlılıklar getirmez. React ve Vue projelerinde yalnızca arka uç tarafında bir veritabanı sürücüsü ve [axios] (https://github.com/axios/axios) kullanır. Angular projeleri yalnızca Angular'a özgü kütüphaneleri kullanır. 154 | 155 | ## Nasıl katkıda bulunulur 156 | 157 | Bir hata bulduysanız veya projeyi nasıl iyileştireceğiniz konusunda bir fikriniz varsa [issue oluşturun](https://github.com/Shpota/goxygen/issues) ve mümkün olan en kısa süre içerisinde düzelteceğiz. Ayrıca Pull Request ile önerebilirsin. Repository'i fork'layın, değişikleri yapın ve bize bir Pull Request gönderin ve kısa süre içerisinde inceleyeceğiz. Ayrıca tüm değişikleri tartıştığımız [Gitter chat](https://gitter.im/goxygen/community) var. 158 | 159 | ## Jenerik 160 | 161 | Goxygen'in logosu [Egon Elbre](https://twitter.com/egonelbre) tarafından yaratılmıştır. 162 | -------------------------------------------------------------------------------- /docs/README_ua.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 | goxygen logo 55 | 56 | **Згенеруйте Web проєкт з використанням Go та сучасних SPA фреймворків.** 57 | 58 | Goxygen зберігає ваш час при створенні нових проєктів. Він 59 | генерує базову структуру проєкту і дозволяє вам відразу ж перейти до 60 | реалізації бізнес логіки без турбот про налаштування. Goxygen створює 61 | back end код на Go, зв'язує його з front end компонентами, додає 62 | `Dockerfile` та `docker-compose` для зручного запуску локально та в 63 | production середовищі. 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
Доступні технології
Front EndAngularReactVue
Back EndGo
База данихMongoDBMySQLPostgreSQL
90 | 91 | ## Вимоги 92 | Ви повинні мати Go 1.16 або новішу версію на вашому комп'ютері. 93 | 94 | ## Як користуватися 95 | ```go 96 | go run github.com/shpota/goxygen@latest init my-app 97 | ``` 98 | В результаті буде згенеровано проєкт в папці `my-app`. 99 | 100 | React і MongoDB використовуються за замовчанням. Ви можете 101 | обрати інший front end фреймворк та іншу базу даних 102 | використовуючи параметри `--frontend` та `--db` відповідно. 103 | Наступна команда генерує проєкт з Vue та PostgreSQL: 104 | 105 | ```go 106 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 107 | ``` 108 | 109 | Параметер `--frontend` може бути встановленим в `angular`, `react` та `vue`. 110 | Параметер `--db` може бути встановленим в `mongo`, `mysql` та `postgres`. 111 | 112 | Згенерований проєкт готовий до запуску з `docker-compose`: 113 | ```sh 114 | cd my-app 115 | docker compose up 116 | ``` 117 | Після завершення збірки, застосунок буде доступний на 118 | http://localhost:8080. 119 | 120 | Більше деталей про те, як працювати зі згенерованим проєктом, 121 | можна знайти в його README. 122 | 123 | ![Showcase](showcase.gif) 124 | 125 | ## Структура згенерованого проєкту (на пиркладі React/MongoDB) 126 | 127 | my-app 128 | ├── server # серверна частина застосунку (Go) 129 | │ ├── db # комунікації MongoDB 130 | │ ├── model # доменні об'єкти 131 | │ ├── web # REST API та Web сервер 132 | │ ├── server.go # вхідна точка серверного коду 133 | │ └── go.mod # опис Go модуля та залежності 134 | ├── webapp 135 | │ ├── public # іконки, статичні файли та index.html 136 | │ ├── src 137 | │ │ ├── App.js # головний React компонент 138 | │ │ ├── App.css # стилі головного компоненту 139 | │ │ ├── index.js # вхідна точка front end застосунку 140 | │ │ └── index.css # глобальні стилі 141 | │ ├── package.json # front end залежності 142 | │ ├── .env.development # API URL для запуску в development середовищі 143 | │ └── .env.production # API URL для запуску в production середовищі 144 | ├── Dockerfile # збирає front end та back end разом 145 | ├── docker-compose.yml # налаштування для запуску в production середовищі 146 | ├── docker-compose-dev.yml # налаштування запуску локальної MongoDB 147 | ├── init-db.js # наповнює базу даних початковими даними 148 | ├── .dockerignore # перерахунок файлів, які ігноруються при збірці Docker 149 | ├── .gitignore 150 | └── README.md # інструкція по використанню проєкту 151 | 152 | Юніт тести та демонстраційні компоненти не відображені в 153 | структурі задля простоти. 154 | 155 | ## Залежності 156 | 157 | Goxygen генерує лише базову структуру проєкту і не нав'язує вам 158 | використання специфічних бібліотек чи утиліт. Згенерований проєкт 159 | використовує лише драйвер бази даних в back end частині та 160 | [axios](https://github.com/axios/axios) для асинхронних REST запитів 161 | (для React i Vue проєктів). 162 | 163 | ## Як долучитися до проєкту 164 | 165 | Якщо ви знайшли помилку або маєте ідеї щодо покращення проєкту, 166 | [відкрийте issue](https://github.com/Shpota/goxygen/issues) 167 | і ми ним займемся. Якщо хочете запропонувати зміни - можете 168 | обговорити їх [в нашому Gitter чаті](https://gitter.im/goxygen/community) 169 | або створити Pull Request. 170 | 171 | ### Подяки 172 | Лого Goxygen створив [Egon Elbre](https://twitter.com/egonelbre). 173 | -------------------------------------------------------------------------------- /docs/README_zh.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | Goxygen 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | goxygen logo 54 | 55 | **分分钟生成一个全栈Web项目(Go,Angular/React/Vue)。** 56 | 57 | Goxygen致力于节省你搭建一个项目的时间。它自动生成一个完全配置好的项目骨架,以方便你可以立即着手实现你的业务逻辑。Goxygen生产后端的Go代码,并将其与前端组件相连,并且为生成的项目提供Dockerfile和docker-compose文件,以便项目在开发环境和生产环境快速运行起来。 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |
Supported Technologies
Front EndAngularReactVue
Back EndGo
DatabaseMongoDBMySQLPostgreSQL
84 | 85 | ## Requirements 86 | 你需要安装Go 1.16或者更新的版本。 87 | 88 | # 如何使用 89 | ```go 90 | go run github.com/shpota/goxygen@latest init my-app 91 | ``` 92 | 这会在你的 `my-app` 目录下生成一个项目。 93 | 94 | By default, it will use React and MongoDB. You can select 95 | a different front end framework and a database using 96 | `--frontend` and `--db` flags. For instance, this command 97 | will create a project with Vue and PostgreSQL: 98 | 99 | ```go 100 | go run github.com/shpota/goxygen@latest init --frontend vue --db postgres my-app 101 | ``` 102 | 103 | The `--frontend` flag accepts `angular`, `react` and `vue`. 104 | The `--db` flag accepts `mongo`, `mysql` and `postgres`. 105 | 106 | 107 | 这个项目已经可以用`docker-compose`来运行了: 108 | ```sh 109 | cd my-app 110 | docker compose up 111 | ``` 112 | build完成之后,就可以在 http://localhost:8080 查看你的Web项目了。 113 | 114 | 你可以在生成的项目里的README里查看更多细节信息。 115 | 116 | ![Showcase](showcase.gif) 117 | 118 | ## 生成的项目的结构 (基于React/MongoDB的项目) 119 | my-app 120 | ├── server # Go项目文件 121 | │ ├── db # MongoDB通信 122 | │ ├── model # 领域对象 123 | │ ├── web # REST APIs, web server 124 | │ ├── server.go # 后端入口 125 | │ └── go.mod # 后端依赖 126 | ├── webapp 127 | │ ├── public # icons, static files, 和 index.html 128 | │ ├── src 129 | │ │ ├── App.js # React main组件 130 | │ │ ├── App.css # App组件样式 131 | │ │ ├── index.js # 前端应用入口 132 | │ │ └── index.css # 全局样式 133 | │ ├── package.json # 前端依赖 134 | │ ├── .env.development # 包含开发环境的API endpoint 135 | │ └── .env.production # 包含生产环境的API endpoint 136 | ├── Dockerfile # 前后端build Dockerfile 137 | ├── docker-compose.yml # 生产环境的docker-compose 138 | ├── docker-compose-dev.yml # 开发使用的docker-compose 139 | ├── init-db.js # 创建一个 MongoDB collection,并写入测试数据 140 | ├── .dockerignore # 指明Docker build的时候要忽略的文件 141 | ├── .gitignore 142 | └── README.md # 如何使用生成repo的教程 143 | 144 | 为了简洁性,诸如单测和样例组件的文件没有显示在这里。 145 | 146 | ## 依赖 147 | 148 | Goxygen只是为你生成一个项目的基本框架,但不强迫你使用任何特定的工具。它不会为你的项目添加任何不必要的依赖,仅有的依赖只有后端的database driver和前端的[axios](https://github.com/axios/axios) 149 | 150 | ## 如何贡献 151 | 152 | 如果你发现了bug或者对于如果改进项目有新的想法,[请提交一个issue](https://github.com/Shpota/goxygen/issues),我们会尽快解决。 153 | 154 | 你也可以直接Pull Request来提交你的修改。Fork这个项目,作出修改之后,发起一个Pull Request,我们会很快review它。 155 | 156 | ### 感谢 157 | Goxygen的logo是由[Egon Elbre](https://twitter.com/egonelbre)创作的。 158 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: minima 2 | 3 | twitter_username: sashashpota 4 | github_username: shpota 5 | linkedin_username: shpota 6 | mastodon: 7 | - username: shpota 8 | instance: mastodon.social 9 | -------------------------------------------------------------------------------- /docs/_includes/footer.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | 6 | 25 | 26 |
27 | 28 |
29 | -------------------------------------------------------------------------------- /docs/_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Goxygen | Generate a Web project with Go and Angular, React or Vue. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /docs/_includes/header.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /docs/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/docs/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/docs/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/docs/favicon-16x16.png -------------------------------------------------------------------------------- /docs/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/docs/favicon-32x32.png -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/docs/favicon.ico -------------------------------------------------------------------------------- /docs/flag-by.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/showcase.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/docs/showcase.gif -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/shpota/goxygen 2 | 3 | go 1.21 4 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | //go:generate go run transform/transformer.go 2 | 3 | package main 4 | 5 | import ( 6 | "github.com/shpota/goxygen/cli" 7 | "github.com/shpota/goxygen/codegen" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | args := os.Args[1:] 13 | cli.Start(os.Stdout, args, codegen.Generate) 14 | } 15 | -------------------------------------------------------------------------------- /templates/.dockerignore: -------------------------------------------------------------------------------- 1 | webapp/node_modules/ 2 | webapp/build/ 3 | -------------------------------------------------------------------------------- /templates/.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.exe~ 3 | *.dll 4 | *.so 5 | *.dylib 6 | *.test 7 | *.out 8 | 9 | webapp/node_modules 10 | webapp/build 11 | webapp/npm-debug.log* 12 | -------------------------------------------------------------------------------- /templates/angular.webapp/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /templates/angular.webapp/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | /build 9 | 10 | # Node 11 | /node_modules 12 | npm-debug.log 13 | yarn-error.log 14 | 15 | # IDEs and editors 16 | .idea/ 17 | .project 18 | .classpath 19 | .c9/ 20 | *.launch 21 | .settings/ 22 | *.sublime-workspace 23 | 24 | # Visual Studio Code 25 | .vscode/* 26 | !.vscode/settings.json 27 | !.vscode/tasks.json 28 | !.vscode/launch.json 29 | !.vscode/extensions.json 30 | .history/* 31 | 32 | # Miscellaneous 33 | /.angular/cache 34 | .sass-cache/ 35 | /connect.lock 36 | /coverage 37 | /libpeerconnection.log 38 | testem.log 39 | /typings 40 | 41 | # System files 42 | .DS_Store 43 | Thumbs.db 44 | -------------------------------------------------------------------------------- /templates/angular.webapp/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /templates/angular.webapp/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /templates/angular.webapp/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /templates/angular.webapp/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "project-name": { 7 | "projectType": "application", 8 | "schematics": {}, 9 | "root": "", 10 | "sourceRoot": "src", 11 | "prefix": "app", 12 | "architect": { 13 | "build": { 14 | "builder": "@angular-devkit/build-angular:browser", 15 | "options": { 16 | "outputPath": "build", 17 | "index": "src/index.html", 18 | "main": "src/main.ts", 19 | "polyfills": [ 20 | "zone.js" 21 | ], 22 | "tsConfig": "tsconfig.app.json", 23 | "assets": [ 24 | "src/favicon.ico", 25 | "src/assets" 26 | ], 27 | "styles": [ 28 | "src/styles.css" 29 | ], 30 | "scripts": [] 31 | }, 32 | "configurations": { 33 | "production": { 34 | "budgets": [ 35 | { 36 | "type": "initial", 37 | "maximumWarning": "500kb", 38 | "maximumError": "1mb" 39 | }, 40 | { 41 | "type": "anyComponentStyle", 42 | "maximumWarning": "2kb", 43 | "maximumError": "4kb" 44 | } 45 | ], 46 | "outputHashing": "all" 47 | }, 48 | "development": { 49 | "buildOptimizer": false, 50 | "optimization": false, 51 | "vendorChunk": true, 52 | "extractLicenses": false, 53 | "sourceMap": true, 54 | "namedChunks": true, 55 | "fileReplacements": [ 56 | { 57 | "replace": "src/environments/environment.ts", 58 | "with": "src/environments/environment.development.ts" 59 | } 60 | ] 61 | } 62 | }, 63 | "defaultConfiguration": "production" 64 | }, 65 | "serve": { 66 | "builder": "@angular-devkit/build-angular:dev-server", 67 | "configurations": { 68 | "production": { 69 | "browserTarget": "project-name:build:production" 70 | }, 71 | "development": { 72 | "browserTarget": "project-name:build:development" 73 | } 74 | }, 75 | "defaultConfiguration": "development" 76 | }, 77 | "extract-i18n": { 78 | "builder": "@angular-devkit/build-angular:extract-i18n", 79 | "options": { 80 | "browserTarget": "project-name:build" 81 | } 82 | }, 83 | "test": { 84 | "builder": "@angular-devkit/build-angular:karma", 85 | "options": { 86 | "polyfills": [ 87 | "zone.js", 88 | "zone.js/testing" 89 | ], 90 | "tsConfig": "tsconfig.spec.json", 91 | "assets": [ 92 | "src/favicon.ico", 93 | "src/assets" 94 | ], 95 | "styles": [ 96 | "src/styles.css" 97 | ], 98 | "scripts": [] 99 | } 100 | } 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /templates/angular.webapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-name", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve --port 3000", 7 | "build": "ng build --configuration production", 8 | "watch": "ng build --watch --configuration development" 9 | }, 10 | "private": true, 11 | "dependencies": { 12 | "@angular/animations": "^16.0.0", 13 | "@angular/common": "^16.0.0", 14 | "@angular/compiler": "^16.0.0", 15 | "@angular/core": "^16.0.0", 16 | "@angular/forms": "^16.0.0", 17 | "@angular/platform-browser": "^16.0.0", 18 | "@angular/platform-browser-dynamic": "^16.0.0", 19 | "@angular/router": "^16.0.0", 20 | "rxjs": "~7.8.0", 21 | "tslib": "^2.3.0", 22 | "zone.js": "~0.13.0" 23 | }, 24 | "devDependencies": { 25 | "@angular-devkit/build-angular": "^16.0.4", 26 | "@angular/cli": "~16.0.4", 27 | "@angular/compiler-cli": "^16.0.0", 28 | "@types/jasmine": "~4.3.0", 29 | "jasmine-core": "~4.6.0", 30 | "karma": "~6.4.0", 31 | "karma-coverage": "~2.2.0", 32 | "karma-jasmine": "~5.1.0", 33 | "karma-jasmine-html-reporter": "~2.0.0", 34 | "typescript": "~5.0.2" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | code { 2 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 3 | monospace; 4 | background-color: #b3e6ff; 5 | } 6 | 7 | .title { 8 | text-align: center; 9 | } 10 | 11 | .logo { 12 | text-align: center; 13 | } 14 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |

{{title}}

3 | 4 |
5 | This project is generated with goxygen. 6 |

7 | The following list of technologies comes from 8 | a REST API call to the Go-based back end. Find 9 | and change the corresponding code in 10 | webapp/src/app/tech/tech.component.ts 11 | and server/web/app.go. 12 |

13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'project-name'; 10 | } 11 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | import { TechComponent } from './tech/tech.component'; 6 | import { HttpClientModule } from '@angular/common/http'; 7 | 8 | @NgModule({ 9 | declarations: [ 10 | AppComponent, 11 | TechComponent 12 | ], 13 | imports: [ 14 | BrowserModule, 15 | HttpClientModule 16 | ], 17 | providers: [], 18 | bootstrap: [AppComponent] 19 | }) 20 | export class AppModule { } 21 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/app/tech/tech.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
  • 3 | {{tech.name}}: {{tech.details}} 4 |
  • 5 |
6 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/app/tech/tech.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { TechService } from './tech.service'; 3 | import { Technology } from './tech.model'; 4 | 5 | @Component({ 6 | selector: 'app-tech', 7 | templateUrl: './tech.component.html' 8 | }) 9 | export class TechComponent implements OnInit { 10 | 11 | technologies: Technology[] = []; 12 | 13 | constructor(private readonly techService: TechService) { } 14 | 15 | ngOnInit() { 16 | this.techService.getTechnologies().subscribe(value => { 17 | this.technologies = value; 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/app/tech/tech.model.ts: -------------------------------------------------------------------------------- 1 | export interface Technology { 2 | name: string; 3 | details: string; 4 | } 5 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/app/tech/tech.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import { Observable } from 'rxjs'; 4 | import { Technology } from './tech.model'; 5 | import { environment } from '../../environments/environment'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class TechService { 11 | 12 | constructor(private readonly httpClient: HttpClient) { } 13 | 14 | getTechnologies(): Observable { 15 | return this.httpClient.get(`${environment.apiUrl}/api/technologies`); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/templates/angular.webapp/src/assets/.gitkeep -------------------------------------------------------------------------------- /templates/angular.webapp/src/environments/environment.development.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | apiUrl: 'http://localhost:8080' 4 | }; 5 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | apiUrl: '' 4 | }; 5 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/favico.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/templates/angular.webapp/src/favico.ico -------------------------------------------------------------------------------- /templates/angular.webapp/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | project-name 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app/app.module'; 4 | 5 | 6 | platformBrowserDynamic().bootstrapModule(AppModule) 7 | .catch(err => console.error(err)); 8 | -------------------------------------------------------------------------------- /templates/angular.webapp/src/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | body { 10 | margin-top: 5%; 11 | padding-right: 5%; 12 | padding-left: 5%; 13 | font-size: larger; 14 | } 15 | 16 | @media screen and (min-width: 800px) { 17 | body { 18 | padding-right: 15%; 19 | padding-left: 15%; 20 | } 21 | } 22 | 23 | @media screen and (min-width: 1600px) { 24 | body { 25 | padding-right: 30%; 26 | padding-left: 30%; 27 | } 28 | } -------------------------------------------------------------------------------- /templates/angular.webapp/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /templates/angular.webapp/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "ES2022", 21 | "useDefineForClassFields": false, 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ] 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /templates/angular.webapp/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /templates/mongo.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16.20-alpine3.18 AS JS_BUILD 2 | COPY webapp /webapp 3 | WORKDIR /webapp 4 | RUN npm install && npm run build 5 | 6 | FROM golang:1.22.1-alpine3.18 AS GO_BUILD 7 | RUN apk update && apk add build-base 8 | COPY server /server 9 | WORKDIR /server 10 | RUN go build -o /go/bin/server 11 | 12 | FROM alpine:3.18.6 13 | COPY --from=JS_BUILD /webapp/build* ./webapp/ 14 | COPY --from=GO_BUILD /go/bin/server ./ 15 | CMD ./server 16 | -------------------------------------------------------------------------------- /templates/mongo.README.md: -------------------------------------------------------------------------------- 1 | # project-name 2 | 3 | ## Environment setup 4 | 5 | You need to have [Go](https://go.dev/), 6 | [Node.js](https://nodejs.org/) and 7 | [Docker](https://www.docker.com/) 8 | installed on your computer. 9 | 10 | Verify the tools by running the following commands: 11 | 12 | ```sh 13 | go version 14 | npm --version 15 | docker --version 16 | ``` 17 | 18 | If you are using Windows you will also need 19 | [gcc](https://gcc.gnu.org/). It comes installed 20 | on Mac and almost all Linux distributions. 21 | 22 | ## Start in development mode 23 | 24 | In the project directory run the command (you might 25 | need to prepend it with `sudo` depending on your setup): 26 | ```sh 27 | docker compose -f docker-compose-dev.yml up 28 | ``` 29 | 30 | This starts a local MongoDB on `localhost:27017`. 31 | The database will be populated with test records 32 | from the [init-db.js](init-db.js) file. 33 | 34 | Navigate to the `server` folder and start the back end: 35 | 36 | ```sh 37 | cd server 38 | go run server.go 39 | ``` 40 | The back end will serve on http://localhost:8080. 41 | 42 | Navigate to the `webapp` folder, install dependencies, 43 | and start the front end development server by running: 44 | 45 | ```sh 46 | cd webapp 47 | npm install 48 | npm start 49 | ``` 50 | The application will be available on http://localhost:3000. 51 | 52 | ## Start in production mode 53 | 54 | Perform: 55 | ```sh 56 | docker compose up 57 | ``` 58 | This will build the application and start it together with 59 | its database. Access the application on http://localhost:8080. 60 | -------------------------------------------------------------------------------- /templates/mongo.docker-compose-dev.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | dev_db: 4 | image: mongo:6.0.3 5 | environment: 6 | MONGO_INITDB_DATABASE: tech 7 | ports: 8 | - 27017:27017 9 | volumes: 10 | - ./init-db.js:/docker-entrypoint-initdb.d/init.js 11 | -------------------------------------------------------------------------------- /templates/mongo.docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | app: 4 | build: . 5 | container_name: app 6 | ports: 7 | - 8080:8080 8 | depends_on: 9 | - db 10 | environment: 11 | profile: prod 12 | db: 13 | image: mongo:6.0.3 14 | container_name: db 15 | environment: 16 | MONGO_INITDB_DATABASE: tech 17 | volumes: 18 | - ./init-db.js:/docker-entrypoint-initdb.d/init.js 19 | -------------------------------------------------------------------------------- /templates/mongo.init-db.js: -------------------------------------------------------------------------------- 1 | db.tech.insert({ 2 | "name": "Go", 3 | "details": "An open source programming language that makes it easy to build simple and efficient software." 4 | }); 5 | db.tech.insert({ 6 | "name": "JavaScript", 7 | "details": "A lightweight, interpreted, or just-in-time compiled programming language with first-class functions." 8 | }); 9 | db.tech.insert({ 10 | "name": "MongoDB", 11 | "details": "A general purpose, document-based, distributed database." 12 | }); 13 | -------------------------------------------------------------------------------- /templates/mongo.server/db/db.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "context" 5 | "go.mongodb.org/mongo-driver/bson" 6 | "go.mongodb.org/mongo-driver/mongo" 7 | "log" 8 | "project-name/model" 9 | ) 10 | 11 | type DB interface { 12 | GetTechnologies() ([]*model.Technology, error) 13 | } 14 | 15 | type MongoDB struct { 16 | collection *mongo.Collection 17 | } 18 | 19 | func NewMongo(client *mongo.Client) DB { 20 | tech := client.Database("tech").Collection("tech") 21 | return MongoDB{collection: tech} 22 | } 23 | 24 | func (m MongoDB) GetTechnologies() ([]*model.Technology, error) { 25 | res, err := m.collection.Find(context.TODO(), bson.M{}) 26 | if err != nil { 27 | log.Println("Error while fetching technologies:", err.Error()) 28 | return nil, err 29 | } 30 | var tech []*model.Technology 31 | err = res.All(context.TODO(), &tech) 32 | if err != nil { 33 | log.Println("Error while decoding technologies:", err.Error()) 34 | return nil, err 35 | } 36 | return tech, nil 37 | } 38 | -------------------------------------------------------------------------------- /templates/mongo.server/go.mod: -------------------------------------------------------------------------------- 1 | module project-name 2 | 3 | go 1.22 4 | 5 | require go.mongodb.org/mongo-driver v1.12.0 6 | 7 | require ( 8 | github.com/golang/snappy v0.0.1 // indirect 9 | github.com/klauspost/compress v1.13.6 // indirect 10 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect 11 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect 12 | github.com/xdg-go/scram v1.1.2 // indirect 13 | github.com/xdg-go/stringprep v1.0.4 // indirect 14 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect 15 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect 16 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect 17 | golang.org/x/text v0.7.0 // indirect 18 | ) 19 | 20 | -------------------------------------------------------------------------------- /templates/mongo.server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= 3 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 4 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 5 | github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= 6 | github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 7 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= 8 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= 9 | github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= 10 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= 11 | github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= 12 | github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= 13 | github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= 14 | github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= 15 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= 16 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= 17 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 18 | go.mongodb.org/mongo-driver v1.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE= 19 | go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0= 20 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 21 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 22 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= 23 | golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 24 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 25 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 26 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 27 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 28 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 29 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 30 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= 31 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 32 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 33 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 34 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 35 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 36 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 37 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 39 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 40 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 41 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 42 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 43 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 44 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 45 | golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= 46 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 47 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 48 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 49 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 50 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 51 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 52 | -------------------------------------------------------------------------------- /templates/mongo.server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "go.mongodb.org/mongo-driver/mongo" 6 | "go.mongodb.org/mongo-driver/mongo/options" 7 | "log" 8 | "os" 9 | "project-name/db" 10 | "project-name/web" 11 | ) 12 | 13 | func main() { 14 | client, err := mongo.Connect(context.TODO(), clientOptions()) 15 | if err != nil { 16 | log.Fatal(err) 17 | } 18 | defer client.Disconnect(context.TODO()) 19 | mongoDB := db.NewMongo(client) 20 | // CORS is enabled only in prod profile 21 | cors := os.Getenv("profile") == "prod" 22 | app := web.NewApp(mongoDB, cors) 23 | err = app.Serve() 24 | log.Println("Error", err) 25 | } 26 | 27 | func clientOptions() *options.ClientOptions { 28 | host := "db" 29 | if os.Getenv("profile") != "prod" { 30 | host = "localhost" 31 | } 32 | return options.Client().ApplyURI( 33 | "mongodb://" + host + ":27017", 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /templates/mysql.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16.20-alpine3.18 AS JS_BUILD 2 | COPY webapp /webapp 3 | WORKDIR /webapp 4 | RUN npm install && npm run build 5 | 6 | FROM golang:1.22.1-alpine3.18 AS GO_BUILD 7 | COPY server /server 8 | WORKDIR /server 9 | RUN go build -o /go/bin/server 10 | 11 | FROM alpine:3.18.6 12 | COPY --from=JS_BUILD /webapp/build* ./webapp/ 13 | COPY --from=GO_BUILD /go/bin/server ./ 14 | CMD ./server 15 | -------------------------------------------------------------------------------- /templates/mysql.README.md: -------------------------------------------------------------------------------- 1 | # project-name 2 | 3 | ## Environment setup 4 | 5 | You need to have [Go](https://go.dev/), 6 | [Node.js](https://nodejs.org/) and 7 | [Docker](https://www.docker.com/) 8 | installed on your computer. 9 | 10 | Verify the tools by running the following commands: 11 | 12 | ```sh 13 | go version 14 | npm --version 15 | docker --version 16 | ``` 17 | 18 | ## Start in development mode 19 | 20 | In the project directory run the command (you might 21 | need to prepend it with `sudo` depending on your setup): 22 | ```sh 23 | docker compose -f docker-compose-dev.yml up 24 | ``` 25 | 26 | This starts a local MySQL database on `localhost:3306`. 27 | The database will be populated with test records from 28 | the [init-db.sql](init-db.sql) file. 29 | 30 | Navigate to the `server` folder and start the back end: 31 | 32 | ```sh 33 | cd server 34 | go run server.go 35 | ``` 36 | The back end will serve on http://localhost:8080. 37 | 38 | Navigate to the `webapp` folder, install dependencies, 39 | and start the front end development server by running: 40 | 41 | ```sh 42 | cd webapp 43 | npm install 44 | npm start 45 | ``` 46 | The application will be available on http://localhost:3000. 47 | 48 | ## Start in production mode 49 | 50 | Perform: 51 | ```sh 52 | docker compose up 53 | ``` 54 | This will build the application and start it together with 55 | its database. Access the application on http://localhost:8080. 56 | -------------------------------------------------------------------------------- /templates/mysql.docker-compose-dev.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | dev_db: 4 | image: mysql:8.0.31 5 | environment: 6 | MYSQL_DATABASE: goxygen 7 | MYSQL_USER: goxygen 8 | MYSQL_PASSWORD: pass 9 | MYSQL_RANDOM_ROOT_PASSWORD: "yes" 10 | ports: 11 | - 3306:3306 12 | volumes: 13 | - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql 14 | -------------------------------------------------------------------------------- /templates/mysql.docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | app: 4 | build: . 5 | container_name: app 6 | ports: 7 | - 8080:8080 8 | depends_on: 9 | - db 10 | environment: 11 | profile: prod 12 | db_pass: pass 13 | db: 14 | image: mysql:8.0.31 15 | container_name: db 16 | environment: 17 | MYSQL_DATABASE: goxygen 18 | MYSQL_USER: goxygen 19 | MYSQL_PASSWORD: pass 20 | MYSQL_RANDOM_ROOT_PASSWORD: "yes" 21 | volumes: 22 | - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql -------------------------------------------------------------------------------- /templates/mysql.init-db.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE technologies ( 2 | name VARCHAR(255), 3 | details VARCHAR(255) 4 | ); 5 | insert into technologies values ( 6 | 'Go', 'An open source programming language that makes it easy to build simple and efficient software.' 7 | ); 8 | insert into technologies values ( 9 | 'JavaScript', 'A lightweight, interpreted, or just-in-time compiled programming language with first-class functions.' 10 | ); 11 | insert into technologies values ( 12 | 'MySQL', 'A powerful, open source object-relational database' 13 | ); 14 | -------------------------------------------------------------------------------- /templates/mysql.server/db/db.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "database/sql" 5 | "project-name/model" 6 | ) 7 | 8 | type DB interface { 9 | GetTechnologies() ([]*model.Technology, error) 10 | } 11 | 12 | type MySQLDB struct { 13 | db *sql.DB 14 | } 15 | 16 | func NewDB(db *sql.DB) DB { 17 | return MySQLDB{db: db} 18 | } 19 | 20 | func (d MySQLDB) GetTechnologies() ([]*model.Technology, error) { 21 | rows, err := d.db.Query("select name, details from technologies") 22 | if err != nil { 23 | return nil, err 24 | } 25 | defer rows.Close() 26 | var tech []*model.Technology 27 | for rows.Next() { 28 | t := new(model.Technology) 29 | err = rows.Scan(&t.Name, &t.Details) 30 | if err != nil { 31 | return nil, err 32 | } 33 | tech = append(tech, t) 34 | } 35 | return tech, nil 36 | } 37 | -------------------------------------------------------------------------------- /templates/mysql.server/go.mod: -------------------------------------------------------------------------------- 1 | module project-name 2 | 3 | go 1.22 4 | 5 | require github.com/go-sql-driver/mysql v1.7.1 6 | -------------------------------------------------------------------------------- /templates/mysql.server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= 2 | github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -------------------------------------------------------------------------------- /templates/mysql.server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | _ "github.com/go-sql-driver/mysql" 6 | "log" 7 | "os" 8 | "project-name/db" 9 | "project-name/web" 10 | ) 11 | 12 | func main() { 13 | d, err := sql.Open("mysql", dataSource()) 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | defer d.Close() 18 | // CORS is enabled only in prod profile 19 | cors := os.Getenv("profile") == "prod" 20 | app := web.NewApp(db.NewDB(d), cors) 21 | err = app.Serve() 22 | log.Println("Error", err) 23 | } 24 | 25 | func dataSource() string { 26 | host := "localhost" 27 | pass := "pass" 28 | if os.Getenv("profile") == "prod" { 29 | host = "db" 30 | pass = os.Getenv("db_pass") 31 | } 32 | return "goxygen:" + pass + "@tcp(" + host + ":3306)/goxygen" 33 | } 34 | -------------------------------------------------------------------------------- /templates/postgres.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16.20-alpine3.18 AS JS_BUILD 2 | COPY webapp /webapp 3 | WORKDIR /webapp 4 | RUN npm install && npm run build 5 | 6 | FROM golang:1.22.1-alpine3.18 AS GO_BUILD 7 | COPY server /server 8 | WORKDIR /server 9 | RUN go build -o /go/bin/server 10 | 11 | FROM alpine:3.18.6 12 | COPY --from=JS_BUILD /webapp/build* ./webapp/ 13 | COPY --from=GO_BUILD /go/bin/server ./ 14 | CMD ./server 15 | -------------------------------------------------------------------------------- /templates/postgres.README.md: -------------------------------------------------------------------------------- 1 | # project-name 2 | 3 | ## Environment setup 4 | 5 | You need to have [Go](https://go.dev/), 6 | [Node.js](https://nodejs.org/) and 7 | [Docker](https://www.docker.com/) 8 | installed on your computer. 9 | 10 | Verify the tools by running the following commands: 11 | 12 | ```sh 13 | go version 14 | npm --version 15 | docker --version 16 | ``` 17 | 18 | ## Start in development mode 19 | 20 | In the project directory run the command (you might 21 | need to prepend it with `sudo` depending on your setup): 22 | ```sh 23 | docker compose -f docker-compose-dev.yml up 24 | ``` 25 | 26 | This starts a local PostgreSQL database on `localhost:5432`. 27 | The database will be populated with test records from the 28 | [init-db.sql](init-db.sql) file. 29 | 30 | Navigate to the `server` folder and start the back end: 31 | 32 | ```sh 33 | cd server 34 | go run server.go 35 | ``` 36 | The back end will serve on http://localhost:8080. 37 | 38 | Navigate to the `webapp` folder, install dependencies, 39 | and start the front end development server by running: 40 | 41 | ```sh 42 | cd webapp 43 | npm install 44 | npm start 45 | ``` 46 | The application will be available on http://localhost:3000. 47 | 48 | ## Start in production mode 49 | 50 | Perform: 51 | ```sh 52 | docker compose up 53 | ``` 54 | This will build the application and start it together with 55 | its database. Access the application on http://localhost:8080. 56 | -------------------------------------------------------------------------------- /templates/postgres.docker-compose-dev.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | dev_db: 4 | image: postgres:15.4-alpine3.18 5 | environment: 6 | POSTGRES_PASSWORD: pass 7 | POSTGRES_USER: goxygen 8 | POSTGRES_DB: goxygen 9 | ports: 10 | - 5432:5432 11 | volumes: 12 | - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql 13 | -------------------------------------------------------------------------------- /templates/postgres.docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | app: 4 | build: . 5 | container_name: app 6 | ports: 7 | - 8080:8080 8 | depends_on: 9 | - db 10 | environment: 11 | profile: prod 12 | db_pass: pass 13 | db: 14 | image: postgres:15.4-alpine3.18 15 | environment: 16 | POSTGRES_PASSWORD: pass 17 | POSTGRES_USER: goxygen 18 | POSTGRES_DB: goxygen 19 | volumes: 20 | - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql -------------------------------------------------------------------------------- /templates/postgres.init-db.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE technologies ( 2 | name VARCHAR(255), 3 | details VARCHAR(255) 4 | ); 5 | insert into technologies values ( 6 | 'Go', 'An open source programming language that makes it easy to build simple and efficient software.' 7 | ); 8 | insert into technologies values ( 9 | 'JavaScript', 'A lightweight, interpreted, or just-in-time compiled programming language with first-class functions.' 10 | ); 11 | insert into technologies values ( 12 | 'PostgreSQL', 'A powerful, open source object-relational database system' 13 | ); 14 | -------------------------------------------------------------------------------- /templates/postgres.server/db/db.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "project-name/model" 5 | "database/sql" 6 | ) 7 | 8 | type DB interface { 9 | GetTechnologies() ([]*model.Technology, error) 10 | } 11 | 12 | type PostgresDB struct { 13 | db *sql.DB 14 | } 15 | 16 | func NewDB(db *sql.DB) DB { 17 | return PostgresDB{db: db} 18 | } 19 | 20 | func (d PostgresDB) GetTechnologies() ([]*model.Technology, error) { 21 | rows, err := d.db.Query("select name, details from technologies") 22 | if err != nil { 23 | return nil, err 24 | } 25 | defer rows.Close() 26 | var tech []*model.Technology 27 | for rows.Next() { 28 | t := new(model.Technology) 29 | err = rows.Scan(&t.Name, &t.Details) 30 | if err != nil { 31 | return nil, err 32 | } 33 | tech = append(tech, t) 34 | } 35 | return tech, nil 36 | } 37 | -------------------------------------------------------------------------------- /templates/postgres.server/go.mod: -------------------------------------------------------------------------------- 1 | module project-name 2 | 3 | go 1.22 4 | 5 | require github.com/lib/pq v1.10.9 6 | -------------------------------------------------------------------------------- /templates/postgres.server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= 2 | github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -------------------------------------------------------------------------------- /templates/postgres.server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "project-name/db" 5 | "project-name/web" 6 | "database/sql" 7 | _ "github.com/lib/pq" 8 | "log" 9 | "os" 10 | ) 11 | 12 | func main() { 13 | d, err := sql.Open("postgres", dataSource()) 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | defer d.Close() 18 | // CORS is enabled only in prod profile 19 | cors := os.Getenv("profile") == "prod" 20 | app := web.NewApp(db.NewDB(d), cors) 21 | err = app.Serve() 22 | log.Println("Error", err) 23 | } 24 | 25 | func dataSource() string { 26 | host := "localhost" 27 | pass := "pass" 28 | if os.Getenv("profile") == "prod" { 29 | host = "db" 30 | pass = os.Getenv("db_pass") 31 | } 32 | return "postgresql://" + host + ":5432/goxygen" + 33 | "?user=goxygen&sslmode=disable&password=" + pass 34 | } 35 | -------------------------------------------------------------------------------- /templates/react.webapp/.env.development: -------------------------------------------------------------------------------- 1 | REACT_APP_API_URL=http://localhost:8080 -------------------------------------------------------------------------------- /templates/react.webapp/.env.production: -------------------------------------------------------------------------------- 1 | REACT_APP_API_URL= -------------------------------------------------------------------------------- /templates/react.webapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-name", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "axios": "~1.2.1", 7 | "react": "~18.2.0", 8 | "react-dom": "~18.2.0", 9 | "react-scripts": "~5.0.1" 10 | }, 11 | "devDependencies": { 12 | "@testing-library/jest-dom": "~5.16.5", 13 | "@testing-library/react": "~13.4.0", 14 | "@testing-library/user-event": "~14.4.3" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": "react-app" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /templates/react.webapp/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/templates/react.webapp/public/favicon.ico -------------------------------------------------------------------------------- /templates/react.webapp/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | project-name 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /templates/react.webapp/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/templates/react.webapp/public/logo192.png -------------------------------------------------------------------------------- /templates/react.webapp/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/templates/react.webapp/public/logo512.png -------------------------------------------------------------------------------- /templates/react.webapp/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "project-name", 3 | "name": "project-name", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /templates/react.webapp/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /templates/react.webapp/src/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-top: 5%; 3 | padding-right: 5%; 4 | padding-left: 5%; 5 | font-size: larger; 6 | } 7 | 8 | @media screen and (min-width: 800px) { 9 | body { 10 | padding-right: 15%; 11 | padding-left: 15%; 12 | } 13 | } 14 | 15 | @media screen and (min-width: 1600px) { 16 | body { 17 | padding-right: 30%; 18 | padding-left: 30%; 19 | } 20 | } 21 | 22 | code { 23 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 24 | monospace; 25 | background-color: #b3e6ff; 26 | } 27 | 28 | .title { 29 | text-align: center; 30 | } 31 | 32 | .logo { 33 | text-align: center; 34 | } 35 | -------------------------------------------------------------------------------- /templates/react.webapp/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './App.css'; 3 | import Logo from './Logo'; 4 | import {Tech} from "./tech/Tech"; 5 | 6 | export function App() { 7 | return ( 8 |
9 |

project-name

10 |
11 |
12 | This project is generated with goxygen. 14 |

The following list of technologies comes from 15 | a REST API call to the Go-based back end. Find 16 | and change the corresponding code 17 | in webapp/src/tech/Tech.js 18 | and server/web/app.go. 19 | 20 |

21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /templates/react.webapp/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {render} from '@testing-library/react'; 3 | import {App} from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const {getByText} = render(); 7 | const linkElement = getByText(/goxygen/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /templates/react.webapp/src/Logo.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Logo = () => { 4 | return ( 5 | 12 | 13 | 14 | 15 | 16 | 17 | 27 | 28 | 29 | 40 | 41 | 42 | 53 | 54 | 55 | 61 | 62 | 70 | 79 | 92 | 93 | 98 | 111 | 122 | 135 | 146 | 159 | 167 | 180 | 194 | 209 | 215 | 225 | 235 | 249 | 250 | 264 | 278 | 291 | 302 | 303 | 304 | 317 | 318 | 319 | ); 320 | }; 321 | 322 | export default Logo; -------------------------------------------------------------------------------- /templates/react.webapp/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | -------------------------------------------------------------------------------- /templates/react.webapp/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import {App} from './App'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /templates/react.webapp/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; -------------------------------------------------------------------------------- /templates/react.webapp/src/tech/Tech.css: -------------------------------------------------------------------------------- 1 | .technologies { 2 | margin-top: 5px; 3 | } 4 | -------------------------------------------------------------------------------- /templates/react.webapp/src/tech/Tech.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from "react"; 2 | import axios from "axios"; 3 | import "./Tech.css" 4 | 5 | export class Tech extends Component { 6 | state = { 7 | technologies: [] 8 | }; 9 | 10 | componentDidMount() { 11 | axios.get(`${process.env.REACT_APP_API_URL}/api/technologies`) 12 | .then(resp => this.setState({ 13 | technologies: resp.data 14 | })); 15 | } 16 | 17 | render() { 18 | const technologies = this.state.technologies.map((technology, i) => 19 |
  • 20 | {technology.name}: {technology.details} 21 |
  • 22 | ); 23 | return ( 24 |
      25 | {technologies} 26 |
    27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /templates/server/model/technology.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | type Technology struct { 4 | Name string `json:"name"` 5 | Details string `json:"details"` 6 | } 7 | -------------------------------------------------------------------------------- /templates/server/web/app.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "encoding/json" 5 | "log" 6 | "net/http" 7 | "project-name/db" 8 | ) 9 | 10 | type App struct { 11 | d db.DB 12 | handlers map[string]http.HandlerFunc 13 | } 14 | 15 | func NewApp(d db.DB, cors bool) App { 16 | app := App{ 17 | d: d, 18 | handlers: make(map[string]http.HandlerFunc), 19 | } 20 | techHandler := app.GetTechnologies 21 | if !cors { 22 | techHandler = disableCors(techHandler) 23 | } 24 | app.handlers["/api/technologies"] = techHandler 25 | app.handlers["/"] = http.FileServer(http.Dir("/webapp")).ServeHTTP 26 | return app 27 | } 28 | 29 | func (a *App) Serve() error { 30 | for path, handler := range a.handlers { 31 | http.Handle(path, handler) 32 | } 33 | log.Println("Web server is available on port 8080") 34 | return http.ListenAndServe(":8080", nil) 35 | } 36 | 37 | func (a *App) GetTechnologies(w http.ResponseWriter, r *http.Request) { 38 | w.Header().Set("Content-Type", "application/json") 39 | technologies, err := a.d.GetTechnologies() 40 | if err != nil { 41 | sendErr(w, http.StatusInternalServerError, err.Error()) 42 | return 43 | } 44 | err = json.NewEncoder(w).Encode(technologies) 45 | if err != nil { 46 | sendErr(w, http.StatusInternalServerError, err.Error()) 47 | } 48 | } 49 | 50 | func sendErr(w http.ResponseWriter, code int, message string) { 51 | resp, _ := json.Marshal(map[string]string{"error": message}) 52 | http.Error(w, string(resp), code) 53 | } 54 | 55 | // Needed in order to disable CORS for local development 56 | func disableCors(h http.HandlerFunc) http.HandlerFunc { 57 | return func(w http.ResponseWriter, r *http.Request) { 58 | w.Header().Set("Access-Control-Allow-Origin", "*") 59 | w.Header().Set("Access-Control-Allow-Methods", "*") 60 | w.Header().Set("Access-Control-Allow-Headers", "*") 61 | h(w, r) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /templates/server/web/app_test.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "net/http/httptest" 7 | "project-name/model" 8 | "testing" 9 | ) 10 | 11 | type MockDb struct { 12 | tech []*model.Technology 13 | err error 14 | } 15 | 16 | func (m *MockDb) GetTechnologies() ([]*model.Technology, error) { 17 | return m.tech, m.err 18 | } 19 | 20 | func TestApp_GetTechnologies(t *testing.T) { 21 | app := App{d: &MockDb{ 22 | tech: []*model.Technology{ 23 | {"Tech1", "Details1"}, 24 | {"Tech2", "Details2"}, 25 | }, 26 | }} 27 | 28 | r, _ := http.NewRequest("GET", "/api/technologies", nil) 29 | w := httptest.NewRecorder() 30 | 31 | app.GetTechnologies(w, r) 32 | 33 | if w.Code != http.StatusOK { 34 | t.Errorf("handler returned wrong status code: got %v want %v", w.Code, http.StatusOK) 35 | } 36 | 37 | want := `[{"name":"Tech1","details":"Details1"},{"name":"Tech2","details":"Details2"}]` + "\n" 38 | if got := w.Body.String(); got != want { 39 | t.Errorf("handler returned unexpected body: got %v want %v", got, want) 40 | } 41 | } 42 | 43 | func TestApp_GetTechnologies_WithDBError(t *testing.T) { 44 | app := App{d: &MockDb{ 45 | tech: nil, 46 | err: errors.New("unknown error"), 47 | }} 48 | 49 | r, _ := http.NewRequest("GET", "/api/technologies", nil) 50 | w := httptest.NewRecorder() 51 | 52 | app.GetTechnologies(w, r) 53 | 54 | if w.Code != http.StatusInternalServerError { 55 | t.Errorf("handler returned wrong status code: got %v want %v", w.Code, http.StatusOK) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /templates/vue.webapp/.env.local: -------------------------------------------------------------------------------- 1 | NODE_ENV=local 2 | VITE_API_URL=http://localhost:8080 -------------------------------------------------------------------------------- /templates/vue.webapp/.env.production: -------------------------------------------------------------------------------- 1 | VITE_API_URL= -------------------------------------------------------------------------------- /templates/vue.webapp/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = { 3 | root: true, 4 | 'extends': [ 5 | 'plugin:vue/vue3-essential', 6 | 'eslint:recommended' 7 | ], 8 | parserOptions: { 9 | ecmaVersion: 'latest' 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /templates/vue.webapp/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /templates/vue.webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | project-name 8 | 9 | 10 |
    11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /templates/vue.webapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-name", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "vite --port 3000", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" 10 | }, 11 | "dependencies": { 12 | "axios": "^1.4.0", 13 | "vue": "^3.3.2" 14 | }, 15 | "devDependencies": { 16 | "@vitejs/plugin-vue": "^4.2.3", 17 | "eslint": "^8.39.0", 18 | "eslint-plugin-vue": "^9.11.0", 19 | "vite": "^4.3.5" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /templates/vue.webapp/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codecook-start/goxygen/775b38e776bf6389e2864f3fe323f44eea5acab0/templates/vue.webapp/public/favicon.ico -------------------------------------------------------------------------------- /templates/vue.webapp/src/App.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 26 | 27 | 68 | -------------------------------------------------------------------------------- /templates/vue.webapp/src/components/TechItems.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | 32 | -------------------------------------------------------------------------------- /templates/vue.webapp/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /templates/vue.webapp/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue()], 9 | resolve: { 10 | alias: { 11 | '@': fileURLToPath(new URL('./src', import.meta.url)) 12 | } 13 | }, 14 | build: { 15 | outDir: 'build', 16 | }, 17 | }) 18 | -------------------------------------------------------------------------------- /transform/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/shpota/goxygen/transform 2 | 3 | go 1.21 4 | -------------------------------------------------------------------------------- /transform/transformer.go: -------------------------------------------------------------------------------- 1 | // Transforms static content form the 'templates' folder 2 | // in the root of the repository to Go code in order to 3 | // distribute it as a part of the module. 4 | package main 5 | 6 | import ( 7 | "bytes" 8 | "log" 9 | "os" 10 | "path/filepath" 11 | "runtime" 12 | "sort" 13 | "strconv" 14 | "strings" 15 | ) 16 | 17 | func main() { 18 | _, filename, _, _ := runtime.Caller(0) 19 | projectRoot := filepath.Join(filepath.Dir(filename), "..") 20 | 21 | var buffer bytes.Buffer 22 | buffer.WriteString(prefix) 23 | textFiles, images := contentFromFiles(filepath.Join(projectRoot, "templates")) 24 | for _, path := range sortedFilePaths(textFiles) { 25 | writeTextFile(path, textFiles[path], &buffer) 26 | } 27 | buffer.WriteString(middle) 28 | for _, path := range sortedImagePaths(images) { 29 | writeImage(path, images[path], &buffer) 30 | } 31 | buffer.WriteString(suffix) 32 | createSourceFile(filepath.Join(projectRoot, "static", "generated.go"), buffer.Bytes()) 33 | log.Println("Completed.") 34 | } 35 | 36 | func createSourceFile(path string, content []byte) { 37 | pkgDir := filepath.Dir(path) 38 | _ = os.MkdirAll(pkgDir, os.ModePerm) 39 | err := os.WriteFile(path, content, 0644) 40 | if err != nil { 41 | log.Fatalln(err) 42 | } 43 | } 44 | 45 | func contentFromFiles(root string) (map[string]string, map[string][]byte) { 46 | textFiles := make(map[string]string) 47 | images := make(map[string][]byte) 48 | for _, originalPath := range filePaths(root) { 49 | path := originalPath[len(root)+1:] 50 | sep := string(os.PathSeparator) 51 | if sep != "/" { 52 | path = strings.Replace(path, sep, "/", -1) 53 | } 54 | ext := filepath.Ext(originalPath) 55 | content, err := os.ReadFile(originalPath) 56 | if err != nil { 57 | log.Fatalln(err) 58 | } 59 | if ext == ".png" || ext == ".ico" { 60 | images[path] = content 61 | } else { 62 | textFiles[path] = string(content) 63 | } 64 | } 65 | return textFiles, images 66 | } 67 | 68 | func writeImage(path string, imgBinary []byte, buffer *bytes.Buffer) { 69 | buffer.WriteString(` "` + path + `": {`) 70 | for _, b := range imgBinary { 71 | buffer.WriteString(strconv.Itoa(int(b)) + ", ") 72 | } 73 | buffer.WriteString("}" + lineSeparator) 74 | } 75 | 76 | func writeTextFile(path string, content string, buffer *bytes.Buffer) { 77 | buffer.WriteString(` "` + path + `": ` + "`") 78 | for _, c := range content { 79 | if string(c) == "`" { 80 | buffer.WriteString("` + " + `"` + "`" + `" + ` + "`") 81 | } else { 82 | buffer.WriteString(string(c)) 83 | } 84 | } 85 | buffer.WriteString("`" + lineSeparator) 86 | } 87 | 88 | func filePaths(dir string) []string { 89 | templates := []string{} 90 | err := filepath.Walk(dir, 91 | func(path string, info os.FileInfo, err error) error { 92 | if err != nil { 93 | return err 94 | } 95 | if !info.IsDir() { 96 | templates = append(templates, path) 97 | } 98 | return nil 99 | }) 100 | if err != nil { 101 | log.Fatalln(err) 102 | } 103 | return templates 104 | } 105 | 106 | func sortedFilePaths(sources map[string]string) []string { 107 | var paths []string 108 | for path := range sources { 109 | paths = append(paths, path) 110 | } 111 | sort.Strings(paths) 112 | return paths 113 | } 114 | 115 | func sortedImagePaths(images map[string][]byte) []string { 116 | var paths []string 117 | for path := range images { 118 | paths = append(paths, path) 119 | } 120 | sort.Strings(paths) 121 | return paths 122 | } 123 | 124 | // Standard header defined at https://golang.org/s/generatedcode 125 | const prefix = `// Code generated from transform/transformer.go; DO NOT EDIT. 126 | 127 | // Package 'static' contains static assets such as 128 | // source code, text files or images generated form 129 | // the 'templates' folder in the root of the repository. 130 | // If a change is made in templates regenerate this file 131 | // by running 'transform/transformer.go'. 132 | package static 133 | 134 | func Sources() map[string]string { 135 | return map[string]string{ 136 | ` 137 | const lineSeparator = `, 138 | ` 139 | const middle = ` } 140 | } 141 | 142 | func Images() map[string][]byte { 143 | return map[string][]byte{ 144 | ` 145 | 146 | const suffix = ` } 147 | }` 148 | -------------------------------------------------------------------------------- /transform/transformer_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSortedImagePaths(t *testing.T) { 8 | images := map[string][]byte{ 9 | "/path2": {2}, 10 | "/path3": {2}, 11 | "/path1": {1}, 12 | } 13 | 14 | paths := sortedImagePaths(images) 15 | 16 | if paths[0] != "/path1" || paths[2] != "/path3" { 17 | t.Error("paths are not sorted") 18 | } 19 | } 20 | 21 | func TestSortedFilePaths(t *testing.T) { 22 | sources := map[string]string{ 23 | "/path2": "src", 24 | "/path3": "src", 25 | "/path1": "src", 26 | } 27 | 28 | paths := sortedFilePaths(sources) 29 | 30 | if paths[0] != "/path1" || paths[2] != "/path3" { 31 | t.Error("paths are not sorted") 32 | } 33 | } 34 | --------------------------------------------------------------------------------