duto 0.260906.0 → 0.261001.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 (75) hide show
  1. package/README.md +34 -12
  2. package/package.json +9 -3
  3. package/src/cli.ts +10 -7
  4. package/src/commands/new.ts +172 -0
  5. package/src/commands/templates/pages/.editorconfig +21 -0
  6. package/src/commands/templates/pages/README.md +21 -0
  7. package/src/commands/templates/pages/_gitignore +24 -0
  8. package/src/commands/templates/pages/components/locale-select.tsx +59 -0
  9. package/src/commands/templates/pages/components/select.tsx +95 -0
  10. package/src/commands/templates/pages/i18n/en.ts +17 -0
  11. package/src/commands/templates/pages/i18n/index.ts +19 -0
  12. package/src/commands/templates/pages/i18n/pt-br.ts +17 -0
  13. package/src/commands/templates/pages/package.json +22 -0
  14. package/src/commands/templates/pages/pages/404.tsx +12 -0
  15. package/src/commands/templates/pages/pages/index.tsx +16 -0
  16. package/src/commands/templates/pages/pages/layout.tsx +24 -0
  17. package/src/commands/templates/pages/style.css +24 -0
  18. package/src/commands/templates/pages/tsconfig.json +54 -0
  19. package/src/commands/templates/pages/types.ts +8 -0
  20. package/src/commands/templates/server/base/.editorconfig +21 -0
  21. package/src/commands/templates/server/base/.env.dev.example +2 -0
  22. package/src/commands/templates/server/base/.env.prod.example +2 -0
  23. package/src/commands/templates/server/base/README.md +29 -0
  24. package/src/commands/templates/server/base/_gitignore +100 -0
  25. package/src/commands/templates/server/base/actions/blog/index.get.ts +9 -0
  26. package/src/commands/templates/server/base/actions/blog/post/[id].get.ts +9 -0
  27. package/src/commands/templates/server/base/actions/index.get.ts +5 -0
  28. package/src/commands/templates/server/base/configs/duto.ts +11 -0
  29. package/src/commands/templates/server/base/configs/roles.ts +5 -0
  30. package/src/commands/templates/server/base/package.json +24 -0
  31. package/src/commands/templates/server/base/tsconfig.json +42 -0
  32. package/src/commands/templates/server/workerd/wrangler.toml +47 -0
  33. package/src/commands/upgrade.ts +30 -0
  34. package/src/index.ts +7 -2
  35. package/src/pages/{commands → cli/commands}/build.ts +13 -7
  36. package/src/pages/{commands → cli/commands}/dev.ts +19 -6
  37. package/src/pages/{commands → cli/commands}/preview.ts +6 -4
  38. package/src/pages/cli/index.ts +10 -0
  39. package/src/pages/cli/utils.ts +126 -0
  40. package/src/pages/client/app.tsx +27 -74
  41. package/src/pages/client/router.ts +15 -281
  42. package/src/pages/compiler/aliases.ts +2 -8
  43. package/src/pages/compiler/ast.ts +1 -538
  44. package/src/pages/compiler/constants.ts +95 -13
  45. package/src/pages/compiler/file.ts +1 -1
  46. package/src/pages/compiler/index.ts +20 -128
  47. package/src/pages/compiler/meta.ts +39 -228
  48. package/src/pages/compiler/routes.ts +4 -5
  49. package/src/pages/compiler/types.ts +11 -101
  50. package/src/pages/compiler/vite-plugin.ts +90 -69
  51. package/src/pages/i18n/client.ts +19 -7
  52. package/src/pages/i18n/element.ts +1 -1
  53. package/src/pages/i18n/server.ts +22 -7
  54. package/src/pages/index.ts +1 -2
  55. package/src/pages/preact/server.ts +1 -1
  56. package/src/server/app.ts +5 -10
  57. package/src/server/auth/ability.ts +1 -1
  58. package/src/server/auth/token.ts +5 -5
  59. package/src/server/cli/commands/build.ts +2 -2
  60. package/src/server/cli/commands/deploy.ts +1 -2
  61. package/src/server/cli/commands/dev.ts +6 -4
  62. package/src/server/cli/commands/routes.ts +0 -1
  63. package/src/server/cli/utils.ts +2 -8
  64. package/src/server/config.ts +18 -3
  65. package/src/server/entry.ts +3 -3
  66. package/src/server/open-api/register.ts +3 -3
  67. package/src/server/open-api/spec.ts +11 -4
  68. package/src/server/request.ts +46 -14
  69. package/src/server/routes.ts +8 -31
  70. package/src/server/utils.ts +25 -0
  71. package/src/utils.ts +43 -2
  72. package/src/pages/commands/dev-old.ts +0 -213
  73. package/src/pages/compiler/island.ts +0 -108
  74. package/src/pages/compiler/utils.ts +0 -5
  75. package/src/server/http.ts +0 -23
@@ -0,0 +1,126 @@
1
+ import { IMPORT, Datte } from 't0n'
2
+ import { join } from 'pathe'
3
+ import { gray, green, yellow, red, cyan } from 't0n/color'
4
+ import type { UserConfig } from 'vite'
5
+
6
+ import { resolveExtension } from '#/compiler/file'
7
+ import config from '#/compiler/vite-plugin'
8
+ import { _root } from '@/utils'
9
+ import { match, match404 } from '#/compiler/routes'
10
+ import type { Metadata, PluginOptions } from '#/compiler/types'
11
+ import { EXTENSIONS_LIST } from '#/compiler/constants'
12
+
13
+ export async function getConfig(name = 'config'): Promise<UserConfig & PluginOptions> {
14
+ let opts = {} as UserConfig
15
+ const file = resolveExtension(name)
16
+ if (file) opts = await IMPORT(join(_root, file), 'default')
17
+ return config(opts)
18
+ }
19
+
20
+ const statusColorMap = new Map([
21
+ [5, red],
22
+ [4, yellow],
23
+ [3, cyan],
24
+ ])
25
+
26
+ const getStatusColor = (status: number) => (statusColorMap.get(Math.floor(status / 100)) ?? green)(String(status))
27
+
28
+ const clients = new Set<Bun.ServerWebSocket<void>>()
29
+ export function reload() {
30
+ for (const ws of clients) {
31
+ if (ws.readyState === WebSocket.OPEN)
32
+ ws.send('reload')
33
+ }
34
+ }
35
+
36
+ export function preview(
37
+ meta: Metadata,
38
+ host: string = '0.0.0.0',
39
+ port: number = 4173
40
+ ) {
41
+ return Bun.serve({
42
+ hostname: host,
43
+ port,
44
+
45
+ websocket: {
46
+ open(ws) {
47
+ clients.add(ws)
48
+ },
49
+ close(ws) {
50
+ clients.delete(ws)
51
+ },
52
+ message() {},
53
+ },
54
+ async fetch(req, server) {
55
+ const start = performance.now()
56
+
57
+ const url = new URL(req.url)
58
+ const path = decodeURIComponent(url.pathname)
59
+ const headers = {
60
+ 'Access-Control-Allow-Origin': '*',
61
+ 'Access-Control-Allow-Methods': 'GET',
62
+ 'Access-Control-Allow-Headers': '*',
63
+ }
64
+
65
+ if (req.method === 'OPTIONS')
66
+ return new Response(null, { status: 204, headers })
67
+
68
+ if (req.headers.get('upgrade') === 'websocket'
69
+ && req.headers.get('sec-websocket-protocol') === 'duto') {
70
+ server.upgrade(req)
71
+ return
72
+ }
73
+
74
+ let status = 500
75
+ let route: string | undefined
76
+ let matched: Bun.MatchedRoute | null | undefined
77
+
78
+ try {
79
+ let res: Response
80
+ const dist = 'dist' // TODO: get from configs
81
+
82
+ let file = Bun.file(join(_root, dist, path))
83
+
84
+ if (await file.exists()) {
85
+ res = new Response(file)
86
+ } else {
87
+ matched = match(path)
88
+ route = matched?.name || match404(meta, path)
89
+ res = new Response(null, { status: 404 })
90
+
91
+ for (const asset of [
92
+ path,
93
+ join(path, 'index'),
94
+ 'index',
95
+ ]) {
96
+ file = Bun.file(join(_root, dist, asset +'.html'))
97
+
98
+ if (await file.exists()) {
99
+ res = new Response(file)
100
+ break
101
+ }
102
+ }
103
+ }
104
+
105
+ status = res.status
106
+ return res
107
+ } catch (err) {
108
+ status = 500
109
+ throw err
110
+ } finally {
111
+ if (EXTENSIONS_LIST.has(path.split('.').pop()!.toLowerCase())) {
112
+ } else if (route || matched) {
113
+ const elapsed = `${Math.max(1, Math.ceil(performance.now() - start))}ms`
114
+
115
+ console.log([
116
+ gray(Datte.dateTime()),
117
+ getStatusColor(status),
118
+ path,
119
+ route && route !== path ? gray(route) : '',
120
+ gray(elapsed),
121
+ ].filter(Boolean).join(' '))
122
+ }
123
+ }
124
+ },
125
+ })
126
+ }
@@ -1,24 +1,27 @@
1
1
  // @ts-ignore
2
- import ':duto/client/hmr'
2
+ import ':duto/hmr'
3
3
 
4
4
  import { render, hydrate, h } from 'preact'
5
5
  import { Switch, Route, Router } from 'wouter-preact'
6
6
  import { useLocation, useParams, useSearchParams, } from 'wouter-preact'
7
7
 
8
- import {
9
- fallbackLocale, locales, messages, routes, routeMap,
10
8
  // @ts-ignore
11
- } from ':duto/i18n'
9
+ import { fallbackLocale, locales, routeMap } from ':duto/i18n'
12
10
  // import i18n from '../i18n/client'
13
11
  import i18n, { updatePickers } from '../i18n/client'
14
12
 
15
- i18n(fallbackLocale, locales, messages, routes, routeMap)
13
+ await i18n(fallbackLocale, locales, {}, {}, routeMap)
16
14
 
15
+ // Custom elements
17
16
  import EI18n from '../i18n/element'
18
- import Island from './island'
19
17
  import Link from './link'
20
18
 
21
- // import Router from './router'
19
+ for (let [tag, el, opts] of [
20
+ ['i-i', EI18n],
21
+ ['i-l', Link, { extends: 'a' }],
22
+ ] as [string, new () => HTMLElement, ElementDefinitionOptions?][]) {
23
+ !customElements.get(tag) && customElements.define(tag, el, opts)
24
+ }
22
25
 
23
26
  import {
24
27
  views, SRoutes,
@@ -27,84 +30,34 @@ import {
27
30
  // @ts-ignore
28
31
  import ':root/styles'
29
32
 
30
- window.$duto = {
31
- sroutes: SRoutes,
32
- location: '/',
33
- navigate: {},
34
- params: {},
35
- search: {},
36
- setSearch: {},
37
- }
38
- import { renderRoute } from './router'
39
- // import { navigate } from 'wouter-preact/use-hash-location'
40
33
 
41
- for (let [tag, el, opts] of [
42
- ['i-i', EI18n],
43
- ['i-l', Link, { extends: 'a' }],
44
- ['i-s', Island],
45
- ] as [string, new () => HTMLElement, ElementDefinitionOptions?][]) {
46
- if (!customElements.get(tag))
47
- customElements.define(tag, el, opts)
48
- }
49
- // Router.load(SRoutes).mount(views)
50
-
51
- // render(h(Router, null,
52
- // h(() => {
53
- // // const __ = useRoute(location.pathname)
54
- // document.body.removeAttribute('hidden')
55
- // const [, navigate] = useLocation()
56
- // // console.log(navigate)
57
- // // this.navigate = navigate
58
-
59
- // // TODO: talvez registrar todos os valores pelo id do elemento em uma fila e atualizar nesse tick...
60
- // // input, select etc registra um update val e aqui popula..
61
- // updatePickers()
62
- // return null
63
- // }, null),
64
- // h(Switch, null,
65
- // h(Route, { path: SRoutes.has(location.pathname) ? location.pathname : '/' }),
66
- // ...views.map(([path, Component, defs, getProps]) =>
67
- // h(Route, {
68
- // path,
69
- // component: ({ params }: { params: Record<string, string> }) => {
70
- // // Trigger async render (updates container imperatively to avoid
71
- // // React/Preact hook rules issues with async components)
72
-
73
- // renderRoute(document.body, Component, params, defs, getProps)
74
- // // Return null — renderRoute will call render() directly on the container
75
- // return null
76
- // },
77
- // })
78
- // ),
34
+ // window.$duto = {
35
+ // sroutes: SRoutes,
36
+ // location: '/',
37
+ // navigate: {},
38
+ // params: {},
39
+ // search: {},
40
+ // setSearch: {},
41
+ // }
42
+ import { renderRoute } from './router'
79
43
 
80
- // ) ), document.body)
81
44
  render(<Router>
82
45
  {h(() => {
83
46
  document.body.removeAttribute('hidden')
47
+ self.$duto = self.$duto || {}
48
+ self.$duto.sroutes = SRoutes
84
49
  const [location, navigate] = useLocation()
85
- window.$duto.location = location
86
- window.$duto.navigate = navigate
87
- window.$duto.params = useParams()
50
+ self.$duto.location = location
51
+ self.$duto.navigate = navigate
52
+ self.$duto.params = useParams()
53
+
88
54
  const [search, setSearch] = useSearchParams()
89
- window.$duto.search = search
90
- window.$duto.setSearch = setSearch
55
+ self.$duto.search = search
56
+ self.$duto.setSearch = setSearch
91
57
 
92
- // TODO: talvez registrar todos os valores pelo id do elemento em uma fila e atualizar nesse tick...
93
- // input, select etc registra um update val e aqui popula..
94
58
  updatePickers()
95
-
96
- // React.useEffect(() => {
97
- // document.body.removeAttribute('hidden');
98
- // navigateRef.current = navigate;
99
- // updatePickers();
100
- // }, [navigate]);
101
- // return null;
102
59
  }, null)}
103
60
  <Switch>
104
- <Route path={SRoutes.has(location.pathname) ? location.pathname : '/'} component={({ params }) => {
105
- delete params[0]
106
- window.$duto.route = { pattern: location.pathname, params, path: location.pathname }
107
- }} />
108
61
  {/* @ts-ignore */}
109
62
  {...views.map(([path, Component, defs, getProps, layouts]) => (
110
63
  <Route path={path} component={({ params }: { params: Record<string, string> }) => {
@@ -1,130 +1,5 @@
1
1
  import { render, h } from 'preact'
2
- // import { render, hydrate, h } from 'preact'
3
- // import { useLocation, Switch, Route, Router } from 'wouter-preact'
4
- // import { matchRoute } from 'wouter-preact'
5
- // import type { Routes, IRoute } from '../types'
6
- import type { Page, GetProps, IRoute } from '@/types'
7
- // import { updatePickers } from '../i18n/client'
8
-
9
- // type Route = [string, Page, IRoute['params'], GetProps]
10
- // type Route = [string, Page] | [string, Page, IRoute['params']] | [string, Page, IRoute['params'], GetProps]
11
- // type Routes = Route[]
12
-
13
-
14
- // type WRouter = {
15
- // navigate: ((href: string) => void) | null,
16
- // routes: Set<string>,
17
- // load: (routes: Set<string>) => WRouter,
18
- // has: (path: string) => boolean,
19
- // // loaded: () => void,
20
- // mount: (routes: Routes) => void,
21
- // // App({ container }: {
22
- // // container: HTMLElement;
23
- // // }): VNode<Attributes & RouterOptions & {
24
- // // children: ComponentChild;
25
- // // }>,
26
- // }
27
-
28
- // export default {
29
- // navigate: null,
30
- // routes: new Set<string>(),
31
- // load(routes: Set<string>) {
32
- // this.routes = routes
33
- // return this
34
- // },
35
- // has(path: string) {
36
- // return this.routes.has(path)
37
- // },
38
- // // loaded() {
39
- // // document.body.removeAttribute('hidden')
40
- // // const [, navigate] = useLocation()
41
- // // this.navigate = navigate
42
-
43
- // // },
44
- // mount(routes: Routes) {
45
- // // ( // If body it was server-rendered — hydrate instead of render
46
- // // document.body.childElementCount > 0
47
- // // ? hydrate
48
- // // : render // @ts-ignore
49
- // // )(this.App(routes), document.body)
50
-
51
- // // @ts-ignore
52
- // render(this.App(routes), document.body)
53
- // },
54
-
55
- // App(routes: Routes, container: HTMLElement = document.body) {
56
- // return h(Router, null,
57
- // h(() => {
58
- // // const __ = useRoute(location.pathname)
59
- // // console.log(__)
60
- // document.body.removeAttribute('hidden')
61
- // const [, navigate] = useLocation()
62
- // this.navigate = navigate
63
-
64
- // // TODO: talvez registrar todos os valores pelo id do elemento em uma fila e atualizar nesse tick...
65
- // // input, select etc registra um update val e aqui popula..
66
- // updatePickers()
67
- // return null
68
- // }, null),
69
- // h(Switch,
70
- // null,
71
-
72
-
73
- // // ...[
74
- // // ['/', 'index.tsx'],
75
- // // ['/about', 'about.tsx'],
76
- // // ['/blog/:slug', 'blog/[slug].tsx'],
77
- // // ['/blog/:slug?', 'blog/[[slug]].tsx'],
78
- // // ['/shop/*', 'shop/[...slug].tsx'],
79
- // // ['/shop/*?', 'shop/[[...slug]].tsx'],
80
- // // ['/:authorId/:postId', '[authorId]/[postId].tsx'],
81
- // // ['/*', '404.tsx'],
82
- // // ['/*', 'not-found.tsx'],
83
- // // ['/users/*', 'users/not-found.tsx'],
84
- // // ].map(([path, name]) =>
85
- // // h(Route, {
86
- // // key: path,
87
- // // path,
88
- // // component: ({ params }: { params: Record<string, string> }) => {
89
-
90
- // // renderRoute(container, () => h("div", { class: "p-8" }, h("h1", { class: "text-white text-xl relative top-2", style: {zIndex:'999', position:'relative', padding: '12px'} }, name), dd(params)), params)
91
- // // // renderRoute(container, () => h("pre", { class: "p-8" }, h("h1", null, JSON.stringify(params))), params)
92
- // // return null
93
- // // },
94
- // // })
95
- // // ),
96
-
97
-
98
- // h(Route, {
99
- // path: this.has(location.pathname) ? location.pathname : '/',
100
- // component: () => null,
101
- // }),
102
-
103
- // ...routes.map(([path, Component, defs, getProps]) =>
104
- // h(Route, {
105
- // // key: path,
106
- // path,
107
- // component: ({ params }: { params: Record<string, string> }) => {
108
- // // Trigger async render (updates container imperatively to avoid
109
- // // React/Preact hook rules issues with async components)
110
-
111
- // renderRoute(container, Component, params, defs, getProps)
112
- // // Return null — renderRoute will call render() directly on the container
113
- // return null
114
- // },
115
- // })
116
- // ),
117
-
118
- // ) )
119
-
120
-
121
- // }
122
- // } as WRouter
123
-
124
- /** Captures wouter's navigate() so the duto:navigate event can call it */
125
- // let _navigate: ((href: string) => void) | null = null
126
-
127
- // ─── Page renderer ────────────────────────────────────────────────────────────
2
+ import type { Page, GetProps, IRoute } from '#/compiler/types'
128
3
 
129
4
  function normalizeParams(
130
5
  raw: Record<string, string>,
@@ -148,22 +23,26 @@ export async function renderRoute(
148
23
  container: HTMLElement,
149
24
  Component: Page,
150
25
  rawParams: Record<string, string>,
151
- paramDefs?: IRoute['params'],
152
- getProps?: GetProps,
26
+ paramDefs?: IRoute['params'] | 0,
27
+ getProps?: GetProps | 0 | 1,
153
28
  layouts?: Page[]
154
29
  ) {
155
30
  while (document.body.firstChild)
156
31
  document.body.removeChild(document.body.firstChild)
157
32
 
158
- // const params = normalizeParams(rawParams, paramDefs)
159
- // const mod = await route._import()
160
-
161
- // let props: Record<string, unknown> = { ...params }
162
-
163
-
164
33
  let props: Record<string, unknown> = paramDefs ? normalizeParams(rawParams, paramDefs) : rawParams
165
34
 
166
- if (typeof getProps === 'function') {
35
+ if (typeof Component === 'string') {
36
+ const mod = await import(Component)
37
+ Component = mod.default
38
+ getProps = getProps === 1 ? mod.getProps : 0
39
+ }
40
+
41
+ // @ts-ignore
42
+ const sProps = self.$duto?.props
43
+ if (typeof sProps === 'object' && sProps !== null) {
44
+ Object.assign(props, sProps)
45
+ } else if (typeof getProps === 'function') {
167
46
  try { // TODO: melhorar tipagem do props
168
47
  const fetched = await Promise.resolve(getProps(props as Record<string, string | string[] | undefined>))
169
48
  props = { ...fetched, ...props }
@@ -172,6 +51,7 @@ export async function renderRoute(
172
51
  }
173
52
  }
174
53
 
54
+
175
55
  let el = h(Component, props as any)
176
56
 
177
57
  const _layouts = layouts ? (Array.isArray(layouts) ? layouts : [layouts]) : []
@@ -179,151 +59,5 @@ export async function renderRoute(
179
59
  el = h(layout, null, el)
180
60
 
181
61
  render(el, container)
182
-
183
- // TODO: melhorar tipagem do props
184
- // render(h(Component, props as any), container)
185
62
  // render(h(Component, props as any), container)
186
63
  }
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
- // TODO: remover..
196
- // function dd(objeto) {
197
- // // Transforma o objeto em string JSON formatada com 2 espaços de recuo
198
- // const json = JSON.stringify(objeto, null, 2);
199
-
200
- // const renderizarJsonColorido = (textoJson) => {
201
- // // Regex para capturar propriedades, strings, números, booleanos, nulls E quebras de linha/espaços explicitamente
202
- // const regex = /(\n|\r\n|\s+|"(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g;
203
- // const partes = [];
204
- // let ultimoIndex = 0;
205
-
206
- // textoJson.replace(regex, (match, p1, offset) => {
207
- // // Adiciona qualquer texto residual intermediário
208
- // if (offset > ultimoIndex) {
209
- // partes.push(textoJson.substring(ultimoIndex, offset));
210
- // }
211
-
212
- // // Se capturar uma quebra de linha, insere a tag <br /> correspondente
213
- // if (match.trim() === '' && (match.includes('\n') || match.includes('\r'))) {
214
- // partes.push(h('br', null));
215
-
216
- // // Se após a quebra de linha houver espaços de indentação, renderiza como spans de espaço
217
- // const espacos = match.replace(/[\n\r]/g, '');
218
- // if (espacos.length > 0) {
219
- // partes.push(h('span', { style: { whiteSpace: 'pre' } }, espacos));
220
- // }
221
- // }
222
- // // Se for apenas espaços de recuo (sem quebra de linha)
223
- // else if (match.trim() === '') {
224
- // partes.push(h('span', { style: { whiteSpace: 'pre' } }, match));
225
- // }
226
- // // Se for um token de dado, aplica a colorização do Laravel
227
- // else {
228
- // let estilo = { color: '#bd93f9' }; // Roxo para números
229
-
230
- // if (/^"/.test(match)) {
231
- // if (/:$/.test(match)) {
232
- // estilo = { color: '#ff79c6', fontWeight: 'bold' }; // Rosa para chaves (keys)
233
- // } else {
234
- // estilo = { color: '#f1fa8c' }; // Amarelo para strings
235
- // }
236
- // } else if (/true|false/.test(match)) {
237
- // estilo = { color: '#8be9fd' }; // Ciano para booleanos
238
- // } else if (/null/.test(match)) {
239
- // estilo = { color: '#6272a4', fontStyle: 'italic' }; // Cinza para nulos
240
- // }
241
-
242
- // partes.push(h('span', { style: estilo }, match));
243
- // }
244
-
245
- // ultimoIndex = offset + match.length;
246
- // });
247
-
248
- // if (ultimoIndex < textoJson.length) {
249
- // partes.push(textoJson.substring(ultimoIndex));
250
- // }
251
-
252
- // return partes;
253
- // };
254
-
255
- // // Estilo do container escuro em tela cheia
256
- // const estiloContainer = {
257
- // background: '#1e1e24', // Grafite escuro elegante
258
- // color: '#f8f8f2',
259
- // padding: '30px',
260
- // fontFamily: '"Fira Code", "Courier New", Courier, monospace',
261
- // fontSize: '14px',
262
- // lineHeight: '1.6',
263
- // overflow: 'auto',
264
- // position: 'fixed',
265
- // top: 0,
266
- // left: 0,
267
- // width: '100vw',
268
- // height: '100vh',
269
- // zIndex: 99,
270
- // textAlign: 'left',
271
- // boxSizing: 'border-box'
272
- // };
273
-
274
- // // Retorna a estrutura h() contendo o bloco quebrado e indentado linha por linha
275
- // return h('div', { style: estiloContainer }, renderizarJsonColorido(json));
276
- // }
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
- // function normalizeParams(
288
- // raw: Record<string, string>,
289
- // paramDefs: IRoute['params']
290
- // ): Record<string, string | string[] | undefined> {
291
- // const result: Record<string, string | string[] | undefined> = {};
292
- // for (const def of paramDefs) {
293
- // const val = raw[def.name];
294
- // if (def.catchAll) {
295
- // result[def.name] = val
296
- // ? val.split('/').filter(Boolean)
297
- // : def.optional ? undefined : []
298
- // } else {
299
- // result[def.name] = val === undefined && def.optional ? undefined : val;
300
- // }
301
- // }
302
- // return result
303
- // }
304
-
305
- // async function renderRoute(
306
- // route: IRoute,
307
- // rawParams: Record<string, string>,
308
- // container: HTMLElement
309
- // ) {
310
- // const params = normalizeParams(rawParams, route.params)
311
- // const mod = await route._import()
312
-
313
- // let props: Record<string, unknown> = { ...params }
314
-
315
- // if (typeof mod.getProps === 'function') {
316
- // try {
317
- // const fetched = await Promise.resolve(mod.getProps(params))
318
- // props = { ...fetched, ...params }
319
- // } catch (e) {
320
- // console.error('[ssg] getProps failed:', e)
321
- // }
322
- // } else {
323
- // // No getProps → re-use SSG props (already in the DOM, nothing to do on first load)
324
- // // props = { ...(window.__SSG_PROPS__ ?? {}), ...params }
325
- // }
326
-
327
- // render(h(mod.default, props as any), container)
328
- // }
329
-
@@ -1,14 +1,8 @@
1
1
  import { join, resolve } from 'node:path'
2
- import { readFileSync } from 'node:fs'
3
2
  import { resolveExtension } from './file'
4
3
 
5
- export function getTsConfig(configPath = './tsconfig.json') {
6
- const content = readFileSync(configPath, 'utf8')
7
- return JSON.parse(content.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, ''))
8
- }
9
-
10
- export function getAliases(root: string) {
11
- const tsconfig = getTsConfig(join(root, './tsconfig.json'))
4
+ export async function getAliases(root: string) {
5
+ const tsconfig = await import(join(root, './tsconfig.json')) // @ts-ignore
12
6
  const compilerOptions = tsconfig.compilerOptions || {}
13
7
  const paths = Object.entries(compilerOptions.paths || {})
14
8
  const baseUrl = compilerOptions.baseUrl || '.'