github.com/pbberlin/go-pwa@v0.0.0-20220328105622-7c26e0ca1ab8/README.md (about) 1 # Golang PWA prototype 2 3 <img src="./app-bucket/img/mascot.webp" style="float: left; width:20%; min-width: 140px; max-width: 20%; margin-right:5%; margin-bottom: 2%;"> 4 5 [![coverage](https://github.com/pbberlin/go-pwa/actions/workflows/codecov.yml/badge.svg)](https://github.com/pbberlin/go-pwa/actions/workflows/codecov.yml) 6 7 Combining the most advanced `golang` techniques 8 into a [Google Lighthouse](https://github.com/GoogleChrome/Lighthouse) approved web app 9 10 * HTTP/2 11 12 * Let's encrypt certification 13 14 * Localhost certificate based on [Filipo Valsordas tool](https://github.com/FiloSottile/mkcert) 15 16 * HTTP redirecting or co-existing 17 18 * Content Security Policies (`CSP`) 19 against CSRF 20 21 * Consistent versioning of HTML, JS, CSS, IMG, 22 _and_ service worker caching 23 24 * Adding a new version at any time by admin http request, 25 while older version files remain accessible 26 27 * Make changes to your app at any time, 28 without breaking service worker caching 29 30 * Server side gzip precompression of CSS and JS files; 31 integrated with version creation 32 33 * Fully developed PWA HTML template 34 35 * Fully developed PWA manifest 36 37 * PWA service worker with `cache-first` for static files 38 39 * Fallback to `/offline.html` for unprecedented user experience 40 41 * PWA service worker register and install 42 43 * PWA service worker pre-caching on install 44 45 * PWA service worker fetch with `cache-first` 46 47 ## Javascript docs 48 49 Finally some comprehensive JS docs 50 51 <https://javascript.info/indexeddb> 52 53 <https://javascript.info/microtask-queue> 54 55 ## Package static 56 57 Preparing and serving static files. 58 59 The package assumes a directory `./app-bucket` 60 containing directories of files by mime-types. 61 `/css`, `/js`, `/img`... 62 63 The package also supports typical special files: 64 `robots.txt`, `service-worker.js`, `favicon.ico` 65 being served under special URIs. 66 67 The package takes care of 68 69 * Execution of templates for special files 70 * Service worker pre-caching 71 * `manifest.json` icon files 72 * Javascript database versioning 73 74 * Mime types by configuration 75 * HTTP caching by configuration 76 77 * Consistent versioning 78 79 * Gzipping by configuration 80 * Handler funcs for HTTP request serving 81 * Registering routes with a http.ServeMux 82 83 Template execution allows custom funcs for arbitrary dynamic preparations. 84 85 A few template execution funcs are provided, 86 to prepare Google PWA config files dynamically 87 from whatever is in the directories under `./app-bucket`. 88 89 All file preparation logic is put together in the HTTP handle func PrepareStatic(...). 90 Thus you whenever you changed any static file contents, 91 call PrepareStatic(), and you get a _consistent_ new version of all static files, 92 and you force your HTTP client (aka browser) to load 93 94 Todo: 95 96 * Make the config loadable via JSON 97 * Javascript templating is done in a highly inappropriate way; cannot get idiomatic way to work 98 * Markdown with some pre-processing is missing 99 100 ## Gorm 101 102 ### Requirements 103 104 * Upsert 105 106 * Associations 1:1, 1:n, m:n 107 108 * Compound unique constraints 109 110 ### Peculiarities 111 112 * Uniqueness indexes should include the deletion date column; 113 fields of gorm.Model must explicitly embedded 114 115 * gorm.Model incurs a lot of noise 116 117 * `create` inserts. 118 Combined with `onConflictUpdate` on conflict it adds DB specific jargon for upsert/merge. 119 120 * `save` first updates by primary key. 121 If no rows are affected, a `select` is issued. If the record does not exist, it gets inserted. 122 123 * `create` and `save` do not associate with existing unique assocations. 124 Instead they fail at creating the same association. 125 Then they create an m:n record with the association ID 0; 126 and without giving any error. 127 128 * Notice with 1:n associations; for example credit cards. 129 If we change the ID of an existing entry, but keep the IDs of the CC associations, 130 those will be removed from the existing entry and associated with the new one. 131 132 * `Association...Apppend` such as in 133 `err = db.Model(&e).Association("Tags").Append(tags)` 134 acts the same way 135 136 * We can and should suppress this unhelpful behavior, 137 by using `onDuplicateIDUpdate.Omit("Tags").Create(&e)` or `...Create` 138 139 * In addition, we cannot store any additional data into the m:n table 140 using the standard funcs