mise manages Node.js and Yarn versions per-project.
mise.toml
[tools]
node = "latest"mise manages Node.js and Yarn versions per-project.
mise.toml
[tools]
node = "latest"| Aspect | Advantages | Drawbacks / Mitigations |
|---|---|---|
| Single tsconfig | One TS project → imports @/backend/... & @/frontend/... just work. | Adonis needs slightly looser TS settings (es2022 libs, node types) than the PWA; solve with tsconfig.backend.json extending the root config. Vite still uses root. |
| No package duplication | Keep one package.json / yarn.lock; dedupe devDeps. | Adonis’s CLI expects its own dependencies. Prefix backend‐only deps with /* backend */ comment to keep clarity or move them to dependencies. |
| Simple import paths | import { set } from "@/api/models/set" works both sides. | Must avoid importing browser-only libs in backend folders; TypeScript path aliases + ESLint plugin “no-browser-imports” for /backend. |
| Shared scripts | npm run dev:full can concurrently start node ace serve --watch and vite. | Vite & Adonis both watch; heavy CPU while both build – mitigated by esbuild + polling off. |
| CI/CD | One pipeline. | Back-end & fro |
| javascript:(function()%7Blet%20synth%20%3D%20window.speechSynthesis%3Blet%20voice%3Bfunction%20setVoice()%20%7Bvoice%20%3D%20synth.getVoices().find(v%20%3D%3E%20v.lang%20%3D%3D%3D%20%22pt-PT%22)%3Bif%20(voice)%20%7BactuallySpeak()%3B%7D%7D%3Bfunction%20handleError(event)%20%7Balert(%22There%20was%20an%20error%22)%3B%7Dfunction%20actuallySpeak()%20%7Blet%20text%20%3D%20document.querySelector(%22textarea%5Bname%3Dtext%5D%22).value%3Bif%20(text.trim()%20%3D%3D%3D%20%22%22)%20%7Breturn%3B%7Dconst%20utterThis%20%3D%20new%20SpeechSynthesisUtterance(text)%3ButterThis.voice%20%3D%20voice%3ButterThis.onerror%20%3D%20handleError%3B%2F*%20utterThis.pitch%20%3D%20pitch.value%3ButterThis.rate%20%3D%20rate.value%3B%20*%2Fsynth.speak(utterThis)%3B%7DsetVoice()%3Bif%20(speechSynthesis.onvoiceschanged%20%3D%3D%3D%20null)%20%7BspeechSynthesis.onvoiceschanged%20%3D%20setVoice%3B%7D%7D)() |
| import Ember from 'ember'; | |
| import { computed } from "@ember/object"; | |
| import { map } from "@ember/object/computed"; | |
| const Folder = Ember.Object.extend({ | |
| subArrays: map('subfolders', 'allChildren'), | |
| allChildren: computed('subfolders.@each.allChildren', 'subArrays.@each.[]', function() { | |
| let children = []; | |
| this.get('subfolders').forEach(folder => { |
| import Ember from 'ember'; | |
| export default Ember.Controller.extend({ | |
| appName: 'Ember Twiddle', | |
| filteredItems: [1,2,3], | |
| unfilteredItems: [4,5,6] | |
| }); |
| import Component from '@ember/component'; | |
| export default Component.extend({ | |
| }); |
| import Ember from 'ember'; | |
| import { next } from '@ember/runloop'; | |
| export default Ember.Component.extend({ | |
| didInsertElement() { | |
| this.list.items.pushObject(this); | |
| } | |
| }); |
| import Ember from 'ember'; | |
| export default Ember.Controller.extend({ | |
| appName: 'Ember Twiddle' | |
| }); |
| import Ember from 'ember'; | |
| export default Ember.Controller.extend({ | |
| appName: 'Ember Twiddle' | |
| }); |