metaowl 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +12 -0
  3. package/build/runtime/bin/metaowl-build.js +10 -0
  4. package/{bin → build/runtime/bin}/metaowl-create.js +96 -177
  5. package/build/runtime/bin/metaowl-dev.js +10 -0
  6. package/build/runtime/bin/metaowl-generate.js +231 -0
  7. package/build/runtime/bin/metaowl-lint.js +58 -0
  8. package/build/runtime/bin/utils.js +68 -0
  9. package/build/runtime/index.js +141 -0
  10. package/build/runtime/modules/app-mounter.js +65 -0
  11. package/build/runtime/modules/auto-import.js +140 -0
  12. package/build/runtime/modules/cache.js +49 -0
  13. package/build/runtime/modules/composables.js +353 -0
  14. package/build/runtime/modules/error-boundary.js +116 -0
  15. package/build/runtime/modules/fetch.js +31 -0
  16. package/build/runtime/modules/file-router.js +205 -0
  17. package/build/runtime/modules/forms.js +193 -0
  18. package/build/runtime/modules/i18n.js +167 -0
  19. package/build/runtime/modules/layouts.js +163 -0
  20. package/build/runtime/modules/link.js +141 -0
  21. package/build/runtime/modules/meta.js +117 -0
  22. package/build/runtime/modules/odoo-rpc.js +264 -0
  23. package/build/runtime/modules/pwa.js +262 -0
  24. package/build/runtime/modules/router.js +389 -0
  25. package/build/runtime/modules/seo.js +186 -0
  26. package/build/runtime/modules/store.js +196 -0
  27. package/build/runtime/modules/templates-manager.js +52 -0
  28. package/build/runtime/modules/test-utils.js +238 -0
  29. package/build/runtime/vite/plugin.js +183 -0
  30. package/eslint.js +29 -0
  31. package/package.json +28 -10
  32. package/CONTRIBUTING.md +0 -49
  33. package/bin/metaowl-build.js +0 -12
  34. package/bin/metaowl-dev.js +0 -12
  35. package/bin/metaowl-generate.js +0 -339
  36. package/bin/metaowl-lint.js +0 -71
  37. package/bin/utils.js +0 -82
  38. package/eslint.config.js +0 -3
  39. package/index.js +0 -328
  40. package/modules/app-mounter.js +0 -104
  41. package/modules/auto-import.js +0 -225
  42. package/modules/cache.js +0 -59
  43. package/modules/composables.js +0 -600
  44. package/modules/error-boundary.js +0 -228
  45. package/modules/fetch.js +0 -51
  46. package/modules/file-router.js +0 -478
  47. package/modules/forms.js +0 -353
  48. package/modules/i18n.js +0 -333
  49. package/modules/layouts.js +0 -431
  50. package/modules/link.js +0 -255
  51. package/modules/meta.js +0 -119
  52. package/modules/odoo-rpc.js +0 -511
  53. package/modules/pwa.js +0 -515
  54. package/modules/router.js +0 -769
  55. package/modules/seo.js +0 -501
  56. package/modules/store.js +0 -409
  57. package/modules/templates-manager.js +0 -89
  58. package/modules/test-utils.js +0 -532
  59. package/test/auto-import.test.js +0 -110
  60. package/test/cache.test.js +0 -55
  61. package/test/composables.test.js +0 -103
  62. package/test/dynamic-routes.test.js +0 -469
  63. package/test/error-boundary.test.js +0 -126
  64. package/test/fetch.test.js +0 -100
  65. package/test/file-router.test.js +0 -55
  66. package/test/forms.test.js +0 -203
  67. package/test/i18n.test.js +0 -188
  68. package/test/layouts.test.js +0 -395
  69. package/test/link.test.js +0 -189
  70. package/test/meta.test.js +0 -146
  71. package/test/odoo-rpc.test.js +0 -547
  72. package/test/pwa.test.js +0 -154
  73. package/test/router-guards.test.js +0 -229
  74. package/test/router.test.js +0 -77
  75. package/test/seo.test.js +0 -353
  76. package/test/store.test.js +0 -476
  77. package/test/templates-manager.test.js +0 -83
  78. package/test/test-utils.test.js +0 -314
  79. package/vite/plugin.js +0 -290
  80. package/vitest.config.js +0 -8
package/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.0] - 2026-04-24
9
+
10
+ ### Changed
11
+
12
+ - **TypeScript migration completed** — the framework source, Vite integration, CLI entrypoints,
13
+ and test suite now use TypeScript as the primary source of truth while preserving the existing
14
+ public API and runtime behavior.
15
+ - **Runtime build output separated from source** — publishable JavaScript is now emitted to
16
+ `build/runtime`, and package `main`, `exports`, and `bin` entries resolve from that generated
17
+ runtime output.
18
+
19
+ ### Removed
20
+
21
+ - **Redundant source JavaScript files** — legacy hand-maintained `.js` source files in `modules/`,
22
+ `bin/`, `vite/`, and the root entrypoint were removed in favor of the TypeScript sources and the
23
+ generated runtime build.
24
+
25
+ ### Added
26
+
27
+ - **Release build workflow** — added dedicated runtime build and release helper scripts for
28
+ clean runtime generation, release checks, and package dry-run validation.
29
+
8
30
  ## [0.4.1] - 2026-03-25
9
31
 
10
32
  ### Added
package/README.md CHANGED
@@ -117,6 +117,18 @@ npm install metaowl
117
117
 
118
118
  `@odoo/owl` is bundled with metaowl and resolved automatically — no separate installation required.
119
119
 
120
+ ### Release Workflow
121
+
122
+ For the package itself, the TypeScript sources remain the source of truth and the publishable runtime files are generated into `build/runtime`.
123
+
124
+ ```bash
125
+ npm run release:check # typecheck + tests
126
+ npm run build:runtime # clean build/runtime and emit JS
127
+ npm run release:pack # full check + build + npm pack --dry-run
128
+ ```
129
+
130
+ `npm pack` and `npm publish` also trigger `prepack`, which rebuilds `build/runtime` automatically.
131
+
120
132
  ---
121
133
 
122
134
  ## Create a New Project
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * metaowl build — lint then production build.
4
+ */
5
+ import { banner, resolveBin, resolveOwnRuntimeBin, run, success } from './utils.js';
6
+ banner('build');
7
+ run('Linting', `node "${resolveOwnRuntimeBin('metaowl-lint')}"`);
8
+ run('Building', `"${resolveBin('vite')}" build`);
9
+ success('Build complete');
10
+ console.log();
@@ -1,71 +1,51 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * metaowl create — scaffold a new metaowl project.
4
- *
5
- * Usage:
6
- * metaowl-create [project-name]
7
- *
8
- * If no name is given, it will be prompted interactively.
9
4
  */
10
- import { createInterface } from 'node:readline/promises'
11
- import { mkdirSync, writeFileSync, existsSync } from 'node:fs'
12
- import { resolve, join, dirname } from 'node:path'
13
- import { banner, step, success, failure, version } from './utils.js'
14
-
15
- banner('create')
16
-
17
- // --- Project name ---
18
- let name = process.argv[2]?.trim()
19
-
5
+ import { mkdirSync, writeFileSync, existsSync } from 'node:fs';
6
+ import { dirname, join, resolve } from 'node:path';
7
+ import { createInterface } from 'node:readline/promises';
8
+ import { banner, failure, step, success, version } from './utils.js';
9
+ banner('create');
10
+ let name = process.argv[2]?.trim() ?? '';
20
11
  if (!name) {
21
- const rl = createInterface({ input: process.stdin, output: process.stdout })
22
- name = (await rl.question(' Project name: ')).trim()
23
- rl.close()
24
- console.log()
12
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
13
+ name = (await rl.question(' Project name: ')).trim();
14
+ rl.close();
15
+ console.log();
25
16
  }
26
-
27
17
  if (!name || !/^[a-zA-Z0-9_-]+$/.test(name)) {
28
- failure('Invalid project name. Use only letters, numbers, hyphens, or underscores.')
29
- process.exit(1)
18
+ failure('Invalid project name. Use only letters, numbers, hyphens, or underscores.');
19
+ process.exit(1);
30
20
  }
31
-
32
- const dest = resolve(process.cwd(), name)
33
-
21
+ const dest = resolve(process.cwd(), name);
34
22
  if (existsSync(dest)) {
35
- failure(`Directory "${name}" already exists.`)
36
- process.exit(1)
23
+ failure(`Directory "${name}" already exists.`);
24
+ process.exit(1);
37
25
  }
38
-
39
- step(`Scaffolding project "${name}"...`)
40
- console.log()
41
-
42
- // --- File writer helper ---
26
+ step(`Scaffolding project "${name}"...`);
27
+ console.log();
43
28
  function write(filePath, content) {
44
- const abs = join(dest, filePath)
45
- mkdirSync(dirname(abs), { recursive: true })
46
- writeFileSync(abs, content, 'utf-8')
47
- console.log(` ${filePath}`)
29
+ const abs = join(dest, filePath);
30
+ mkdirSync(dirname(abs), { recursive: true });
31
+ writeFileSync(abs, content, 'utf-8');
32
+ console.log(` ${filePath}`);
48
33
  }
49
-
50
- // --- package.json ---
51
34
  write('package.json', JSON.stringify({
52
- name,
53
- version: '0.1.0',
54
- type: 'module',
55
- scripts: {
56
- dev: 'metaowl-dev',
57
- build: 'metaowl-build',
58
- generate: 'metaowl-generate',
59
- lint: 'metaowl-lint'
60
- },
61
- dependencies: {
62
- metaowl: `^${version}`
63
- }
64
- }, null, 2) + '\n')
65
-
66
- // --- vite.config.js ---
67
- write('vite.config.js',
68
- `import { metaowlConfig } from 'metaowl/vite'
35
+ name,
36
+ version: '0.1.0',
37
+ type: 'module',
38
+ scripts: {
39
+ dev: 'metaowl-dev',
40
+ build: 'metaowl-build',
41
+ generate: 'metaowl-generate',
42
+ lint: 'metaowl-lint'
43
+ },
44
+ dependencies: {
45
+ metaowl: `^${version}`
46
+ }
47
+ }, null, 2) + '\n');
48
+ write('vite.config.js', `import { metaowlConfig } from 'metaowl/vite'
69
49
 
70
50
  export default async () => {
71
51
  return metaowlConfig({
@@ -73,45 +53,31 @@ export default async () => {
73
53
  pagesDir: 'src/pages'
74
54
  })
75
55
  }
76
- `)
77
-
78
- // --- eslint.config.js ---
79
- write('eslint.config.js',
80
- `import { eslintConfig } from 'metaowl/eslint'
56
+ `);
57
+ write('eslint.config.js', `import { eslintConfig } from 'metaowl/eslint'
81
58
 
82
59
  export default eslintConfig
83
- `)
84
-
85
- // --- postcss.config.cjs ---
86
- write('postcss.config.cjs',
87
- `const { createPostcssConfig } = require('metaowl/postcss')
60
+ `);
61
+ write('postcss.config.cjs', `const { createPostcssConfig } = require('metaowl/postcss')
88
62
 
89
63
  module.exports = createPostcssConfig()
90
- `)
91
-
92
- // --- jsconfig.json ---
64
+ `);
93
65
  write('jsconfig.json', JSON.stringify({
94
- extends: './node_modules/metaowl/config/jsconfig.base.json',
95
- compilerOptions: {
96
- baseUrl: '.',
97
- paths: {
98
- '@pages/*': ['src/pages/*'],
99
- '@components/*': ['src/components/*']
100
- }
101
- },
102
- include: ['src']
103
- }, null, 2) + '\n')
104
-
105
- // --- .gitignore ---
106
- write('.gitignore',
107
- `node_modules/
66
+ extends: './node_modules/metaowl/config/jsconfig.base.json',
67
+ compilerOptions: {
68
+ baseUrl: '.',
69
+ paths: {
70
+ '@pages/*': ['src/pages/*'],
71
+ '@components/*': ['src/components/*']
72
+ }
73
+ },
74
+ include: ['src']
75
+ }, null, 2) + '\n');
76
+ write('.gitignore', `node_modules/
108
77
  dist/
109
78
  .env
110
- `)
111
-
112
- // --- src/index.html ---
113
- write('src/index.html',
114
- `<!doctype html>
79
+ `);
80
+ write('src/index.html', `<!doctype html>
115
81
  <html lang="en">
116
82
  <head>
117
83
  <meta charset="UTF-8" />
@@ -123,28 +89,19 @@ write('src/index.html',
123
89
  <script type="module" src="/metaowl.js"></script>
124
90
  </body>
125
91
  </html>
126
- `)
127
-
128
- // --- src/metaowl.js ---
129
- write('src/metaowl.js',
130
- `import { boot, Fetch } from 'metaowl'
92
+ `);
93
+ write('src/metaowl.js', `import { boot, Fetch } from 'metaowl'
131
94
 
132
95
  Fetch.configure({
133
96
  baseUrl: import.meta.env.VITE_API_URL ?? ''
134
97
  })
135
98
 
136
99
  boot()
137
- `)
138
-
139
- // --- src/css.js ---
140
- write('src/css.js',
141
- `// Global styles — import shared CSS here.
100
+ `);
101
+ write('src/css.js', `// Global styles — import shared CSS here.
142
102
  // Component and page CSS files are auto-imported by the metaowl Vite plugin.
143
- `)
144
-
145
- // --- src/pages/index/Index.js ---
146
- write('src/pages/index/Index.js',
147
- `import { Component } from '@odoo/owl'
103
+ `);
104
+ write('src/pages/index/Index.js', `import { Component } from '@odoo/owl'
148
105
  import { Meta } from 'metaowl'
149
106
  import AppHeader from '@components/AppHeader/AppHeader'
150
107
  import AppFooter from '@components/AppFooter/AppFooter'
@@ -157,11 +114,8 @@ export default class Index extends Component {
157
114
  Meta.title('Home — ${name}')
158
115
  }
159
116
  }
160
- `)
161
-
162
- // --- src/pages/index/Index.xml ---
163
- write('src/pages/index/Index.xml',
164
- `<templates>
117
+ `);
118
+ write('src/pages/index/Index.xml', `<templates>
165
119
  <t t-name="Index">
166
120
  <div class="layout">
167
121
  <AppHeader />
@@ -172,11 +126,8 @@ write('src/pages/index/Index.xml',
172
126
  </div>
173
127
  </t>
174
128
  </templates>
175
- `)
176
-
177
- // --- src/pages/index/index.css ---
178
- write('src/pages/index/index.css',
179
- `.layout {
129
+ `);
130
+ write('src/pages/index/index.css', `.layout {
180
131
  display: flex;
181
132
  flex-direction: column;
182
133
  min-height: 100vh;
@@ -186,31 +137,22 @@ write('src/pages/index/index.css',
186
137
  flex: 1;
187
138
  padding: 2rem;
188
139
  }
189
- `)
190
-
191
- // --- src/components/AppHeader/AppHeader.js ---
192
- write('src/components/AppHeader/AppHeader.js',
193
- `import { Component } from '@odoo/owl'
140
+ `);
141
+ write('src/components/AppHeader/AppHeader.js', `import { Component } from '@odoo/owl'
194
142
 
195
143
  export default class AppHeader extends Component {
196
144
  static template = 'AppHeader'
197
145
  }
198
- `)
199
-
200
- // --- src/components/AppHeader/AppHeader.xml ---
201
- write('src/components/AppHeader/AppHeader.xml',
202
- `<templates>
146
+ `);
147
+ write('src/components/AppHeader/AppHeader.xml', `<templates>
203
148
  <t t-name="AppHeader">
204
149
  <header class="app-header">
205
150
  <span class="app-header__logo">${name}</span>
206
151
  </header>
207
152
  </t>
208
153
  </templates>
209
- `)
210
-
211
- // --- src/components/AppHeader/AppHeader.css ---
212
- write('src/components/AppHeader/AppHeader.css',
213
- `.app-header {
154
+ `);
155
+ write('src/components/AppHeader/AppHeader.css', `.app-header {
214
156
  display: flex;
215
157
  align-items: center;
216
158
  padding: 0 1.5rem;
@@ -222,31 +164,22 @@ write('src/components/AppHeader/AppHeader.css',
222
164
  font-weight: 600;
223
165
  font-size: 1.1rem;
224
166
  }
225
- `)
226
-
227
- // --- src/components/AppFooter/AppFooter.js ---
228
- write('src/components/AppFooter/AppFooter.js',
229
- `import { Component } from '@odoo/owl'
167
+ `);
168
+ write('src/components/AppFooter/AppFooter.js', `import { Component } from '@odoo/owl'
230
169
 
231
170
  export default class AppFooter extends Component {
232
171
  static template = 'AppFooter'
233
172
  }
234
- `)
235
-
236
- // --- src/components/AppFooter/AppFooter.xml ---
237
- write('src/components/AppFooter/AppFooter.xml',
238
- `<templates>
173
+ `);
174
+ write('src/components/AppFooter/AppFooter.xml', `<templates>
239
175
  <t t-name="AppFooter">
240
176
  <footer class="app-footer">
241
177
  <span>Built with metaowl</span>
242
178
  </footer>
243
179
  </t>
244
180
  </templates>
245
- `)
246
-
247
- // --- src/components/AppFooter/AppFooter.css ---
248
- write('src/components/AppFooter/AppFooter.css',
249
- `.app-footer {
181
+ `);
182
+ write('src/components/AppFooter/AppFooter.css', `.app-footer {
250
183
  display: flex;
251
184
  align-items: center;
252
185
  justify-content: center;
@@ -255,11 +188,8 @@ write('src/components/AppFooter/AppFooter.css',
255
188
  color: #6b7280;
256
189
  border-top: 1px solid #e5e7eb;
257
190
  }
258
- `)
259
-
260
- // --- .cursorrules ---
261
- write('.cursorrules',
262
- `# MetaOwl Project Rules
191
+ `);
192
+ write('.cursorrules', `# MetaOwl Project Rules
263
193
 
264
194
  ## Framework Overview
265
195
  This is a MetaOwl application - a lightweight meta-framework for Odoo OWL built on top of Vite.
@@ -296,7 +226,7 @@ This is a MetaOwl application - a lightweight meta-framework for Odoo OWL built
296
226
 
297
227
  ## File Structure
298
228
  - pages/ - Route components
299
- - components/ - Reusable components
229
+ - components/ - Reusable components
300
230
  - layouts/ - Page layouts (optional)
301
231
  - metaowl.js - App entry point
302
232
 
@@ -309,11 +239,8 @@ This is a MetaOwl application - a lightweight meta-framework for Odoo OWL built
309
239
  ## Documentation
310
240
  - See README.md for full API reference
311
241
  - See metaowl module docs for detailed API
312
- `)
313
-
314
- // --- CLAUDE.md ---
315
- write('CLAUDE.md',
316
- `# ${name} - MetaOwl Project
242
+ `);
243
+ write('CLAUDE.md', `# ${name} - MetaOwl Project
317
244
 
318
245
  ## Quick Start for Claude Code
319
246
 
@@ -329,7 +256,7 @@ This project uses MetaOwl, a meta-framework for Odoo OWL on Vite.
329
256
  \`\`\`
330
257
  src/
331
258
  ├── metaowl.js # App bootstrap
332
- ├── pages/ # Route components (file-based routing)
259
+ ├── pages/ # Route components
333
260
  │ └── index/
334
261
  │ ├── Index.js # Page component
335
262
  │ ├── Index.xml # OWL template
@@ -420,7 +347,7 @@ src/
420
347
  │ └── AdminLayout.xml
421
348
  \`\`\`
422
349
 
423
- Layout Template uses \`<t t-slot=\"default\"/>\` to render page content:
350
+ Layout Template uses \`<t t-slot="default"/>\` to render page content:
424
351
  \`\`\`xml
425
352
  <t t-name="AdminLayout">
426
353
  <div class="layout-admin">
@@ -461,11 +388,8 @@ Meta.canonical('https://example.com/page')
461
388
  - File-based routing uses directory name, not file name
462
389
  - OWL uses xml templates, not JSX
463
390
  - Static properties are required (template, components)
464
- `)
465
-
466
- // --- llms.txt ---
467
- write('llms.txt',
468
- `# MetaOwl LLM Context
391
+ `);
392
+ write('llms.txt', `# MetaOwl LLM Context
469
393
 
470
394
  ## Framework Identity
471
395
  MetaOwl is a lightweight meta-framework for Odoo OWL (Odoo Web Library) applications, built on Vite. It provides file-based routing, state management, and app mounting.
@@ -611,11 +535,8 @@ export default class ComponentName extends Component {
611
535
  - README.md - Full documentation
612
536
  - https://github.com/odoo/owl - OWL framework
613
537
  - https://vitejs.dev - Vite documentation
614
- `)
615
-
616
- // --- .github/copilot-instructions.md ---
617
- write('.github/copilot-instructions.md',
618
- `# GitHub Copilot Instructions for MetaOwl
538
+ `);
539
+ write('.github/copilot-instructions.md', `# GitHub Copilot Instructions for MetaOwl
619
540
 
620
541
  ## About This Project
621
542
  This is a MetaOwl application - a lightweight meta-framework for Odoo OWL (Odoo Web Library) built on Vite.
@@ -731,15 +652,13 @@ router.beforeEach((to, from, next) => {
731
652
  - Scope CSS to components
732
653
  - Use Meta helpers for SEO
733
654
  - Leverage Store for shared state
734
- `)
735
-
736
- // --- Done ---
737
- console.log()
738
- success(`Project "${name}" ready`)
739
- console.log()
740
- console.log(' Next steps:')
741
- console.log()
742
- console.log(` cd ${name}`)
743
- console.log(` npm install`)
744
- console.log(` npm run dev`)
745
- console.log()
655
+ `);
656
+ console.log();
657
+ success(`Project "${name}" ready`);
658
+ console.log();
659
+ console.log(' Next steps:');
660
+ console.log();
661
+ console.log(` cd ${name}`);
662
+ console.log(' npm install');
663
+ console.log(' npm run dev');
664
+ console.log();
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * metaowl dev — start the Vite development server.
4
+ */
5
+ import { execSync } from 'node:child_process';
6
+ import { banner, cwd, resolveBin, step } from './utils.js';
7
+ banner('dev');
8
+ step('Starting development server...');
9
+ console.log();
10
+ execSync(`"${resolveBin('vite')}"`, { stdio: 'inherit', cwd });