duto 0.260808.0 → 0.260915.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 (98) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +35 -13
  3. package/package.json +54 -13
  4. package/src/cli.ts +45 -0
  5. package/src/commands/new.ts +147 -0
  6. package/src/commands/templates/base/.editorconfig +21 -0
  7. package/src/commands/templates/base/.env.dev.example +2 -0
  8. package/src/commands/templates/base/.env.prod.example +2 -0
  9. package/src/commands/templates/base/README.md +29 -0
  10. package/src/commands/templates/base/_gitignore +100 -0
  11. package/src/commands/templates/base/actions/blog/index.get.ts +9 -0
  12. package/src/commands/templates/base/actions/blog/post/[id].get.ts +9 -0
  13. package/src/commands/templates/base/actions/index.get.ts +5 -0
  14. package/src/commands/templates/base/configs/duto.ts +11 -0
  15. package/src/commands/templates/base/configs/roles.ts +5 -0
  16. package/src/commands/templates/base/package.json +24 -0
  17. package/src/commands/templates/base/tsconfig.json +42 -0
  18. package/src/commands/templates/workerd/wrangler.toml +47 -0
  19. package/src/commands/upgrade.ts +30 -0
  20. package/src/enum.ts +2 -0
  21. package/src/index.d.ts +61 -0
  22. package/src/index.ts +19 -23
  23. package/src/middleware.ts +2 -0
  24. package/src/{cli → pages/cli}/commands/build.ts +13 -7
  25. package/src/{cli → pages/cli}/commands/dev.ts +11 -4
  26. package/src/{cli → pages/cli}/commands/preview.ts +6 -4
  27. package/src/pages/cli/index.ts +10 -0
  28. package/src/{cli → pages/cli}/utils.ts +4 -5
  29. package/src/{client → pages/client}/app.tsx +1 -1
  30. package/src/{client → pages/client}/router.ts +1 -1
  31. package/src/{compiler → pages/compiler}/file.ts +1 -1
  32. package/src/{compiler → pages/compiler}/index.ts +2 -4
  33. package/src/{compiler → pages/compiler}/meta.ts +2 -2
  34. package/src/{compiler → pages/compiler}/routes.ts +1 -1
  35. package/src/{compiler → pages/compiler}/types.ts +10 -0
  36. package/src/{compiler → pages/compiler}/vite-plugin.ts +20 -45
  37. package/src/{i18n → pages/i18n}/client.ts +2 -2
  38. package/src/{i18n → pages/i18n}/element.ts +1 -1
  39. package/src/{i18n → pages/i18n}/server.ts +1 -1
  40. package/src/pages/index.ts +28 -0
  41. package/src/{preact → pages/preact}/server.ts +1 -1
  42. package/src/server/adapter/aws.ts +4 -0
  43. package/src/server/adapter/workerd.ts +4 -0
  44. package/src/server/app.ts +91 -0
  45. package/src/server/auth/ability.ts +72 -0
  46. package/src/server/auth/authnz.ts +86 -0
  47. package/src/server/auth/index.ts +5 -0
  48. package/src/server/auth/token.ts +147 -0
  49. package/src/server/auth/types.ts +2 -0
  50. package/src/server/cli/commands/build.ts +41 -0
  51. package/src/server/cli/commands/deploy.ts +81 -0
  52. package/src/server/cli/commands/dev.ts +279 -0
  53. package/src/server/cli/commands/make.ts +98 -0
  54. package/src/server/cli/commands/migrate.ts +93 -0
  55. package/src/server/cli/commands/routes.ts +78 -0
  56. package/src/server/cli/index.ts +27 -0
  57. package/src/server/cli/stubs.ts +39 -0
  58. package/src/server/cli/types.ts +3 -0
  59. package/src/server/cli/utils.ts +437 -0
  60. package/src/server/config.ts +19 -0
  61. package/src/server/db/d1.d.ts +1 -0
  62. package/src/server/db/d1.ts +1 -0
  63. package/src/server/db/dynamodb.d.ts +1 -0
  64. package/src/server/db/dynamodb.ts +1 -0
  65. package/src/server/db/index.ts +1 -0
  66. package/src/server/entry.ts +19 -0
  67. package/src/server/handle.ts +30 -0
  68. package/src/server/middlewares/auth.ts +40 -0
  69. package/src/server/middlewares/logger.ts +30 -0
  70. package/src/server/open-api/register.ts +29 -0
  71. package/src/server/open-api/spec.ts +114 -0
  72. package/src/server/request.ts +265 -0
  73. package/src/server/response.ts +142 -0
  74. package/src/server/routes.ts +473 -0
  75. package/src/server/types.ts +142 -0
  76. package/src/server/utils/environment.ts +17 -0
  77. package/src/server/utils.ts +71 -0
  78. package/src/server/validator.ts +70 -0
  79. package/src/utils.ts +15 -0
  80. package/src/cli/commands/dev-old.ts +0 -213
  81. package/src/cli/index.ts +0 -28
  82. package/src/compiler/utils.ts +0 -5
  83. /package/src/{client → pages/client}/hmr.ts +0 -0
  84. /package/src/{client → pages/client}/island.ts +0 -0
  85. /package/src/{client → pages/client}/link.ts +0 -0
  86. /package/src/{client → pages/client}/storage.ts +0 -0
  87. /package/src/{compiler → pages/compiler}/aliases.ts +0 -0
  88. /package/src/{compiler → pages/compiler}/assets.ts +0 -0
  89. /package/src/{compiler → pages/compiler}/ast.ts +0 -0
  90. /package/src/{compiler → pages/compiler}/constants.ts +0 -0
  91. /package/src/{compiler → pages/compiler}/island.ts +0 -0
  92. /package/src/{components → pages/components}/link.tsx +0 -0
  93. /package/src/{preact → pages/preact}/client-dev.ts +0 -0
  94. /package/src/{preact → pages/preact}/client.ts +0 -0
  95. /package/src/{preact → pages/preact}/context.ts +0 -0
  96. /package/src/{preact → pages/preact}/signals.ts +0 -0
  97. /package/src/{preact → pages/preact}/static-html.ts +0 -0
  98. /package/src/{preact → pages/preact}/types.ts +0 -0
@@ -0,0 +1,47 @@
1
+ name = "duto-api"
2
+ main = ".duto/index.js"
3
+ compatibility_date = "2026-08-06"
4
+
5
+ # workers_dev = false
6
+ # preview_urls = false
7
+ no_bundle = true
8
+ send_metrics = false
9
+ compatibility_flags = [ "no_nodejs_compat", "no_nodejs_compat_v2" ]
10
+
11
+ # route = "example.com"
12
+ # route = { pattern = "api.example.com", custom_domain = true }
13
+
14
+ # [[routes]]
15
+ # pattern = "api.example.com/*"
16
+ # zone_name = "example.com"
17
+ # [[routes]]
18
+ # pattern = "api.example.com"
19
+ # custom_domain = true
20
+
21
+ # [observability]
22
+ # enabled = true
23
+ # head_sampling_rate = 0.1 # 10% of requests are logged
24
+
25
+ # PAID
26
+ # [limits]
27
+ # # The maximum CPU time allowed per invocation, in milliseconds
28
+ # cpu_ms = 100
29
+
30
+ # Bindings (KV, D1, R2..)
31
+ # kv_namespaces = []
32
+ # d1_databases = []
33
+
34
+ # [[d1_databases]]
35
+ # binding = "SCRIPT_NAME"
36
+ # database_name = "DB_NAME"
37
+ # database_id = "DB_UUID"
38
+ # preview_database_id = "PREVIEW_UUID"
39
+ # migrations_table = "MIGRATION_TABLE_NAME"
40
+ # migrations_dir = "migrations/sql"
41
+ # persist_to = "./.wrangler/state"
42
+
43
+ # [env.production]
44
+ # name = "rajt-api-prod"
45
+
46
+ # [vars]
47
+ # API_HOST = "api.example.com"
@@ -0,0 +1,30 @@
1
+ import { command } from 't0n/cli'
2
+ import { dim, green } from 't0n/color'
3
+ import { event, error, step, log, rn } from 't0n/log'
4
+ import { _root } from '@/utils'
5
+ import { version } from '!/package.json'
6
+
7
+ import { createSpinner } from 'nanospinner'
8
+
9
+ export default command({
10
+ meta: {
11
+ name: 'upgrade',
12
+ description: '📄 Upgrade to latest version of Duto\n',
13
+ },
14
+ async run({ args }) { // @ts-ignore
15
+ const spinner = createSpinner('Upgrading...').start()
16
+
17
+ const proc = Bun.spawn(['bun', 'update', '-g', 'duto'], { stdout: 'ignore', stderr: 'ignore' })
18
+ const exitCode = await proc.exited
19
+
20
+ if (exitCode === 0) {
21
+ spinner.success({ text: 'Upgraded' })
22
+ } else {
23
+ spinner.error({ text: `Falha ao atualizar duto (exit ${exitCode})` })
24
+ process.exit(exitCode)
25
+ }
26
+
27
+ event(green('Congrats!') + ` You're already on the latest version of Duto.`)
28
+ // event(green('Congrats!') + ` You're already on the latest version of Duto ${dim(`(which is v${version})`)}`)
29
+ },
30
+ })
package/src/enum.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { Enum } from 't0n'
2
+ export type { EnumStatic, EnumValue, EnumType } from 't0n'
package/src/index.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ /// <reference types='bun-types' />
2
+ /// <reference types='node' />
3
+
4
+ // export { }
5
+
6
+ import * as Duto from './'
7
+
8
+ declare global {
9
+ // Duto
10
+ var __st: number
11
+ var __hmr: boolean
12
+
13
+ type Req = Duto.Req
14
+ type Res = Duto.Res
15
+ type $v = Duto.$v
16
+ type IRequest = Duto.IRequest
17
+ type IResponse = Duto.IResponse
18
+ type IValidator = Duto.IValidator
19
+
20
+ type Context = Duto.Context
21
+ type Next = Duto.Next
22
+
23
+ type Abilities = Duto.Abilities
24
+ type Roles = Duto.Roles
25
+
26
+ type EnumStatic = Duto.EnumStatic
27
+ type EnumValue = Duto.EnumValue
28
+ type EnumType = Duto.EnumType
29
+
30
+
31
+ // Bun:test
32
+ var test: typeof import('bun:test').test
33
+ var describe: typeof import('bun:test').describe
34
+ var it: typeof import('bun:test').it
35
+ var expect: typeof import('bun:test').expect
36
+ // Hooks
37
+ var beforeAll: typeof import('bun:test').beforeAll
38
+ var afterAll: typeof import('bun:test').afterAll
39
+ var beforeEach: typeof import('bun:test').beforeEach
40
+ var afterEach: typeof import('bun:test').afterEach
41
+ // Mocking
42
+ var mock: typeof import('bun:test').mock
43
+ var vi: typeof import('bun:test').vi
44
+ var jest: typeof import('bun:test').jest
45
+ var spyOn: typeof import('bun:test').spyOn
46
+ // Utils
47
+ var setSystemTime: typeof import('bun:test').setSystemTime
48
+ var setDefaultTimeout: typeof import('bun:test').setDefaultTimeout
49
+ // Types
50
+ var Test: typeof import('bun:test').Test
51
+ var Describe: typeof import('bun:test').Describe
52
+ var Expect: typeof import('bun:test').Expect
53
+ var Mock: typeof import('bun:test').Mock
54
+ var TestOptions: typeof import('bun:test').TestOptions
55
+ var Matchers: typeof import('bun:test').Matchers
56
+ // Namespace
57
+ namespace jest {
58
+ var fn: typeof import('bun:test').vi.fn
59
+ var mock: typeof import('bun:test').vi.mock
60
+ }
61
+ }
package/src/index.ts CHANGED
@@ -1,28 +1,24 @@
1
- export {
2
- Redirect,
3
- useLocation, useParams, useSearch, useSearchParams,
4
- matchRoute,
5
- } from 'wouter-preact'
1
+ export * from './pages'
6
2
 
7
- export {
8
- t, r, d,
9
- getLocale, setLocale,
10
- isPrefixed,
11
- } from './i18n/client'
3
+ export { default as Response } from './server/response'
4
+ export * from './server/config'
12
5
 
13
- export { local } from './client/storage'
6
+ export {
7
+ Enum,
8
+ Envir, hasEnv, getEnv, setEnv, addEnv, removeEnv
9
+ } from 't0n'
10
+ export type { EnumStatic, EnumValue, EnumType } from 't0n'
14
11
 
15
- export const navigate = <S = any>(
16
- to: string | URL,
17
- options?: { replace?: boolean; state?: S; transition?: boolean }
18
- ) => {
19
- if (window?.$duto?.sroutes?.has(to)) {
20
- location.pathname = to
21
- return
22
- }
12
+ export type {
13
+ IRequest, IRequest as Req, IRequest as $req,
14
+ IResponse, IResponse as Res, IResponse as $res,
15
+ IValidator, IValidator as $v,
16
+ Context, Next,
17
+ } from './server/types'
23
18
 
24
- const n = window?.$duto?.navigate || useLocation()[1]
25
- n(to, options)
26
- }
19
+ // Auth
20
+ export { Ability } from './server/auth/ability'
21
+ export { Authnz } from './server/auth/authnz'
22
+ export { Token } from './server/auth/token'
27
23
 
28
- export { Link } from './components/link'
24
+ export type { Abilities, Roles } from './server/auth/types'
@@ -0,0 +1,2 @@
1
+ export { auth } from './server/middlewares/auth'
2
+ // export { cors } from './server/middlewares/cors'
@@ -1,22 +1,29 @@
1
1
  import { build } from 'vite'
2
- import { filesize } from 'filesize'
2
+ import { setEnv } from 't0n'
3
3
  import { command } from 't0n/cli'
4
4
  import { dim, underline } from 't0n/color'
5
5
  import { wait, error, rn, event } from 't0n/log'
6
- import { meta } from '@/vite-plugin'
7
- import { getConfig } from '~/utils'
8
- import type { SummaryMetadata } from '@/types'
6
+ import { meta } from '#/compiler/vite-plugin'
7
+ import type { SummaryMetadata } from '#/compiler/types'
8
+ import { getConfig } from '../utils'
9
+ import { filesize } from '@/utils'
9
10
 
10
11
  export default command({
11
12
  meta: {
12
13
  name: 'build',
13
14
  description: '🗂️ Perform the build for production\n',
14
15
  },
15
- args: {
16
+ args: {
17
+ minify: {
18
+ description: 'Minify the result',
19
+ type: 'boolean',
20
+ default: true,
21
+ },
16
22
  },
17
23
  async run({ args }) {
18
- global.__hmr = !!args?.hmr
19
24
  wait('Building..')
25
+ setEnv('duto.hmr', !!args?.hmr)
26
+ setEnv('duto.minify', args.minify ?? true)
20
27
 
21
28
  try {
22
29
  await build(await getConfig())
@@ -65,7 +72,6 @@ export default command({
65
72
  event(`Builded successfully${st ? dim(` in ${st} ms`) : ''}`)
66
73
  } catch (e: any) {
67
74
  error(e)
68
- // error('Build failed:', e?.message || e)
69
75
  process.exit(0)
70
76
  } finally {
71
77
  rn()
@@ -2,9 +2,10 @@ import { command, watch, killProcess } from 't0n/cli'
2
2
  import { dim } from 't0n/color'
3
3
  import { error, log, rn } from 't0n/log'
4
4
  import { withPort } from 't0n/port'
5
- import { getMetadata } from '@/meta'
5
+ import { getMetadata } from '#/compiler/meta'
6
6
  import { _root } from '@/utils'
7
- import { getConfig, preview, reload } from '~/utils'
7
+ import { getConfig, preview, reload } from '../utils'
8
+ import { getEnv, setEnv } from 't0n'
8
9
 
9
10
  export const args = {
10
11
  port: {
@@ -28,8 +29,11 @@ export default command({
28
29
  args,
29
30
  async run({ args }) {
30
31
  const config = await getConfig()
31
- const desiredPort = args.port ? Number(args.port) : (config?.preview?.port ? Number(config.preview.port) : 3000)
32
- const host = args.host ? String(args.host) : (config?.preview?.host ? String(config.preview.host) : 'localhost')
32
+ const duto = getEnv('duto', {})
33
+ const desiredPort = Number(args.port || duto?.dev?.port || 3000)
34
+ const host = String(args.host || duto?.dev?.host || 'localhost')
35
+ // const desiredPort = args.port ? Number(args.port) : (config?.preview?.port ? Number(config.preview.port) : 3000)
36
+ // const host = args.host ? String(args.host) : (config?.preview?.host ? String(config.preview.host) : 'localhost')
33
37
 
34
38
  let buildProcess: Bun.Subprocess | null = null
35
39
 
@@ -48,6 +52,9 @@ export default command({
48
52
  }
49
53
 
50
54
  withPort(desiredPort, async (port) => {
55
+ setEnv('duto.dev.port', port)
56
+ setEnv('duto.dev.host', host)
57
+
51
58
  const ignore = [
52
59
  /(^|[\/\\])\.(duto|git|cache|vscode|idea|next|nuxt|nyc_output)([\/\\]|$)/,
53
60
  /(^|[\/\\])(node_modules|tmp|dist|build|out|coverage)([\/\\]|$)/,
@@ -2,10 +2,11 @@ import { command } from 't0n/cli'
2
2
  import { dim } from 't0n/color'
3
3
  import { error, log, rn } from 't0n/log'
4
4
  import { withPort } from 't0n/port'
5
- import { getMetadata } from '@/meta'
5
+ import { getMetadata } from '#/compiler/meta'
6
6
  import { _root } from '@/utils'
7
7
  import { args } from './dev'
8
- import { getConfig, preview } from '~/utils'
8
+ import { getConfig, preview } from '../utils'
9
+ import { getEnv } from 't0n'
9
10
 
10
11
  export default command({
11
12
  meta: {
@@ -15,8 +16,9 @@ export default command({
15
16
  args,
16
17
  async run({ args }) {
17
18
  const config = await getConfig()
18
- const desiredPort = args.port ? Number(args.port) : (config?.preview?.port ? Number(config.preview.port) : 3000)
19
- const host = args.host ? String(args.host) : (config?.preview?.host ? config.preview.host as string : 'localhost')
19
+ const duto = getEnv('duto', {})
20
+ const desiredPort = Number(args.port || duto?.dev?.port || 3000)
21
+ const host = String(args.host || duto?.dev?.host || 'localhost')
20
22
 
21
23
  withPort(desiredPort, async (port) => {
22
24
  try {
@@ -0,0 +1,10 @@
1
+ import { join } from 'pathe'
2
+
3
+ const cmd = (c: string) => join(import.meta.dirname, 'commands', c)
4
+
5
+ export default {
6
+ dev: cmd('dev'),
7
+ build: cmd('build'),
8
+ preview: cmd('preview'),
9
+ // deploy: cmd('deploy'),
10
+ }
@@ -3,12 +3,11 @@ import { join } from 'pathe'
3
3
  import { gray, green, yellow, red, cyan } from 't0n/color'
4
4
  import type { UserConfig } from 'vite'
5
5
 
6
- import { resolveExtension } from '@/file'
7
- import config from '@/vite-plugin'
6
+ import { resolveExtension } from '#/compiler/file'
7
+ import config from '#/compiler/vite-plugin'
8
8
  import { _root } from '@/utils'
9
- import { match, match404 } from '@/routes'
10
- import type { Metadata, PluginOptions } from '@/types'
11
- import { getMetadata } from '@/meta'
9
+ import { match, match404 } from '#/compiler/routes'
10
+ import type { Metadata, PluginOptions } from '#/compiler/types'
12
11
 
13
12
  export async function getConfig(name = 'config'): Promise<UserConfig & PluginOptions> {
14
13
  let opts = {} as UserConfig
@@ -1,5 +1,5 @@
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'
@@ -3,7 +3,7 @@ import { render, h } from 'preact'
3
3
  // import { useLocation, Switch, Route, Router } from 'wouter-preact'
4
4
  // import { matchRoute } from 'wouter-preact'
5
5
  // import type { Routes, IRoute } from '../types'
6
- import type { Page, GetProps, IRoute } from '@/types'
6
+ import type { Page, GetProps, IRoute } from '#/compiler/types'
7
7
  // import { updatePickers } from '../i18n/client'
8
8
 
9
9
  // type Route = [string, Page, IRoute['params'], GetProps]
@@ -1,7 +1,7 @@
1
1
  import { extname, join } from 'node:path'
2
2
  import { existsSync } from 'node:fs'
3
3
  import { EXTENSIONS, FILE_EXTENSIONS } from './constants'
4
- import type { Metadata } from '@/types'
4
+ import type { Metadata } from './types'
5
5
 
6
6
  const extensionCache = new Map<string, string | null>()
7
7
  export function resolveExtension(filePath: string): string | null {
@@ -15,7 +15,6 @@ import type { IRoute, Metadata, RouteParams, StaticProps, SummaryMetadata } from
15
15
 
16
16
  // import i18n from '../client/i18n'
17
17
  import { setLocale } from '../i18n/client'
18
- import { log, substep } from 't0n/log'
19
18
 
20
19
 
21
20
 
@@ -162,13 +161,12 @@ export async function renderPage(
162
161
  config.build.outDir,
163
162
  pathname +'.html'
164
163
  )
165
- const outHTML = minify.minify(
164
+ const outHTML = meta.minify ? minify.minify(
166
165
  Buffer.from(html),
167
166
  {}
168
167
  // options != null ? options : {},
169
- )
168
+ ) : html
170
169
  await mkdir(dirname(outFile), {recursive: true})
171
- // await writeFile(outFile, outHTML, 'utf-8')
172
170
  await Bun.write(outFile, outHTML)
173
171
 
174
172
  const key = '/'+ pathname
@@ -7,7 +7,7 @@
7
7
  import { dirname, extname, join } from 'node:path'
8
8
  import { readdirSync } from 'node:fs'
9
9
 
10
- import { IMPORT, JSJSON, newID } from 't0n'
10
+ import { getEnv, IMPORT, JSJSON, newID } from 't0n'
11
11
 
12
12
  import { getAliases } from './aliases'
13
13
  import { EXT_RE, DYNAMIC_RE, INTERNAL_RE, LAYOUT_RE, NF_NAMES } from './constants'
@@ -257,7 +257,7 @@ export async function getLayouts(meta: Metadata, path: string) {
257
257
  }
258
258
 
259
259
  export async function getMetadata(root: string, dir: string) {
260
- const meta = { root, dir } as Metadata
260
+ const meta = { root, dir, ...getEnv('duto', {}) } as Metadata
261
261
  meta.summary = new Map<string, SummaryMetadata>()
262
262
 
263
263
  meta.i18n = await getI18n(meta)
@@ -1,5 +1,5 @@
1
1
  import { join } from 'pathe'
2
- import { _root } from './utils'
2
+ import { _root } from '@/utils'
3
3
  import type { IRoute, Metadata } from './types'
4
4
  import { dirname } from 'node:path'
5
5
  import { NF_NAMES } from './constants'
@@ -1,4 +1,5 @@
1
1
  // import type { ComponentType, FunctionComponent, VNode } from 'preact'
2
+ import type { Platform } from '$/cli/types'
2
3
  import type { FunctionComponent, VNode } from 'preact'
3
4
 
4
5
  export type PluginOptions = {
@@ -41,6 +42,15 @@ export type SummaryMetadata = {
41
42
  export type Metadata = {
42
43
  root: string,
43
44
  dir: string,
45
+ type: 'pages' | 'server',
46
+ platform: Platform,
47
+ dev: {
48
+ host: string,
49
+ port: number,
50
+ },
51
+ hmr: boolean,
52
+ minify: boolean,
53
+
44
54
  aliases: Record<string, string>,
45
55
  map: Map<string, FileMetadata>,
46
56
  violations: Map<string, DepMetadata[]>,
@@ -1,6 +1,6 @@
1
1
  // REF: https://github.com/tailwindlabs/tailwindcss/blob/main/packages/%40tailwindcss-vite/src/index.ts
2
2
 
3
- import { existsSync, readFileSync, rmSync } from 'node:fs'
3
+ import { existsSync, rmSync } from 'node:fs'
4
4
  import { join } from 'node:path'
5
5
  import { defineConfig } from 'vite'
6
6
 
@@ -9,11 +9,10 @@ import tailwind from '@tailwindcss/vite'
9
9
 
10
10
  import { EXT_RE } from './constants'
11
11
  import { setAsset, setChunk, setEntry } from './assets'
12
- import { renderPage } from './'
12
+ import { renderPage } from '.'
13
13
  import { removeExports, resolveImport } from './ast'
14
14
  import { getMetadata } from './meta'
15
15
 
16
- import type { IncomingMessage, ServerResponse } from 'node:http'
17
16
  import type {
18
17
  // Plugin,
19
18
  UserConfig, ConfigEnv, ResolvedConfig,
@@ -23,12 +22,12 @@ import type {
23
22
  PluginOption,
24
23
  } from 'vite'
25
24
  import type { Metadata, PluginOptions } from './types'
26
- import { _duto, _root } from './utils'
25
+ import { _pages, _root } from '@/utils'
27
26
 
28
27
  const VIRTUAL_ID = ':duto'
29
28
  const RESOLVED_ID = '\0'+ VIRTUAL_ID
30
29
 
31
- export const config = (opts: UserConfig & PluginOptions) => {
30
+ export const config = (opts: UserConfig & PluginOptions) => { // @ts-ignore
32
31
  if (!opts.root) opts.root = _root
33
32
  if (!opts.pagesDir) opts.pagesDir = 'pages',
34
33
 
@@ -57,7 +56,6 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
57
56
  root = _root, // process.env.npm_config_local_prefix || process.env.PWD || process.cwd() || __dirname,
58
57
  pagesDir = 'pages',
59
58
  } = options
60
-
61
59
  // let metadata: Metadata
62
60
 
63
61
  const PAGES_RE = new RegExp(`\/${pagesDir}\/.*\.(tsx?|jsx?)$`, 'i')
@@ -101,26 +99,6 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
101
99
 
102
100
  return opts
103
101
  },
104
-
105
- // configurePreviewServer(server: PreviewServer) {
106
- // const distDir = join(server.config.root, 'dist')
107
-
108
- // server.middlewares.use((req: IncomingMessage, res: ServerResponse, next: (err?: any) => void) => {
109
- // if (req.url && !existsSync(join(distDir, req.url.split('?')[0]))) {
110
- // const notFound = join(distDir, '404.html')
111
-
112
- // if (existsSync(notFound)) {
113
- // res.statusCode = 404
114
- // res.setHeader('Content-Type', 'text/html')
115
- // .end(readFileSync(notFound, 'utf-8'))
116
- // return
117
- // }
118
- // }
119
-
120
- // next()
121
- // })
122
- // },
123
-
124
102
  },
125
103
 
126
104
  {
@@ -133,8 +111,7 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
133
111
  // },
134
112
 
135
113
  async config(conf: UserConfig, env: ConfigEnv) {
136
- // if (!metadata)
137
- metadata = await getMetadata(root, pagesDir)
114
+ metadata = await getMetadata(root as string, pagesDir)
138
115
 
139
116
  // console.log(metadata.map)
140
117
  // console.log(metadata.violations)
@@ -146,8 +123,8 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
146
123
  conf.build.manifest = false
147
124
  conf.build.modulePreload = { polyfill: false }
148
125
 
149
- conf.build.minify = true
150
- conf.build.cssMinify = true //////
126
+ conf.build.minify = metadata.minify
127
+ conf.build.cssMinify = metadata.minify
151
128
 
152
129
  conf.build.rolldownOptions = conf.build.rolldownOptions || {}
153
130
  conf.build.rolldownOptions.preserveEntrySignatures = 'exports-only' ///
@@ -157,20 +134,22 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
157
134
  ...Object.keys(metadata.pages),
158
135
  ...metadata.assets,
159
136
  ]
137
+
138
+ const filePrefix = metadata.minify ? '' : '[name].'
160
139
  // conf.build.rolldownOptions.input = ':duto/client/app.tsx'
161
140
  conf.build.rolldownOptions.output = {
162
141
  hoistTransitiveImports: false,
163
142
  format: 'esm',
164
- minifyInternalExports: true,
143
+ minifyInternalExports: metadata.minify,
165
144
 
166
145
  // manualChunks: {
167
146
  // vendor: ['preact', '@preact/signals', 'wouter-preact'],
168
147
  // },
169
148
  // preserveModules: true,
170
149
  preserveModulesRoot: '/',
171
- assetFileNames: '[hash][extname]',
172
- entryFileNames: '[hash].js',
173
- chunkFileNames: '[hash].js',
150
+ assetFileNames: filePrefix +'[hash][extname]',
151
+ entryFileNames: filePrefix +'[hash].js',
152
+ chunkFileNames: filePrefix +'[hash].js',
174
153
 
175
154
  // chunkFileNames: '[name].[hash].js',
176
155
  // entryFileNames: 'assets/[name].js',
@@ -213,13 +192,13 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
213
192
  if (!id.startsWith(VIRTUAL_ID)) return null
214
193
 
215
194
  if (EXT_RE.test(id) && id.includes('/')) {
216
- const path = join(_duto, id.replace(VIRTUAL_ID, ''))
195
+ const path = join(_pages, id.replace(VIRTUAL_ID, ''))
217
196
  setEntry(id, path)
218
197
  return path
219
198
  }
220
199
 
221
- if (id.endsWith('/hmr') && global.__hmr)
222
- return join(_duto, id.replace(VIRTUAL_ID, '') + '.ts')
200
+ if (id.endsWith('/hmr') && metadata.hmr)
201
+ return join(_pages, 'client', id.replace(VIRTUAL_ID, '') + '.ts')
223
202
 
224
203
  return id.replace(VIRTUAL_ID, RESOLVED_ID)
225
204
  },
@@ -245,7 +224,7 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
245
224
  continue
246
225
  }
247
226
 
248
- if (file.type === 'asset' && file?.originalFileName?.endsWith('duto/client/app.tsx'))
227
+ if (file.type === 'asset' && file?.originalFileName?.endsWith('duto/pages/client/app.tsx'))
249
228
  file.source += 'd-b,d-p,i-d,i-s,i-i{display:contents}'
250
229
 
251
230
  if (file.type === 'asset' && file.fileName.endsWith('.css')) {
@@ -296,10 +275,10 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
296
275
  },
297
276
 
298
277
  async closeBundle() {
299
- for (const [_filePath, page] of metadata.pages) {
278
+ for (const [_filePath, page] of metadata.pages) // {
300
279
  await renderPage(metadata, config, page)
301
280
  // const mod = await server.ssrLoadModule(_filePath)
302
- }
281
+ // }
303
282
 
304
283
  rmSync(join(metadata.root, 'tmp'), {recursive: true, force: true})
305
284
  // await server.close()
@@ -311,12 +290,8 @@ export function plugin(options: PluginOptions = {}): PluginOption[] {
311
290
  // console.log(this.getModuleInfo(id))
312
291
 
313
292
  const stripped = removeExports(id, code, stripTarget)
314
- if (!stripped || stripped === code) return null
315
293
 
316
- return {
317
- code: stripped,
318
- map: null, // source maps omitted for brevity, add if needed
319
- }
294
+ return (!stripped || stripped === code) ? null : { code: stripped, map: null }
320
295
  },
321
296
 
322
297
  },
@@ -1,6 +1,6 @@
1
1
  import { h, type JSX } from 'preact'
2
- import { local } from '#/storage'
3
- import { navigate } from '../'
2
+ import { local } from '#/client/storage'
3
+ import { navigate } from '..'
4
4
 
5
5
  const accepted = (lang: string | undefined, locales: string[] = [], fallback: string) => lang && locales.includes(lang) ? lang : fallback
6
6
 
@@ -1,4 +1,4 @@
1
- import { local } from '#/storage'
1
+ import { local } from '#/client/storage'
2
2
  import { t, _prefixed } from './client'
3
3
 
4
4
  export default class EI18n extends HTMLElement {
@@ -1,7 +1,7 @@
1
1
  import { join } from 'node:path'
2
2
  import { IMPORT, JSJSON } from 't0n'
3
3
 
4
- import type { Metadata, I18nMetadata } from '@/types'
4
+ import type { Metadata, I18nMetadata } from '#/compiler/types'
5
5
  import { existsSync } from 'node:fs'
6
6
 
7
7
  export default async function getI18n(meta: Metadata) {
@@ -0,0 +1,28 @@
1
+ export {
2
+ Redirect,
3
+ useLocation, useParams, useSearch, useSearchParams,
4
+ matchRoute,
5
+ } from 'wouter-preact'
6
+
7
+ export {
8
+ t, r, d,
9
+ getLocale, setLocale,
10
+ isPrefixed,
11
+ } from './i18n/client'
12
+
13
+ export { local } from './client/storage'
14
+
15
+ export const navigate = <S = any>(
16
+ to: string | URL,
17
+ options?: { replace?: boolean; state?: S; transition?: boolean }
18
+ ) => {
19
+ if (window?.$duto?.sroutes?.has(to)) {
20
+ location.pathname = to
21
+ return
22
+ }
23
+
24
+ const n = window?.$duto?.navigate || useLocation()[1]
25
+ n(to, options)
26
+ }
27
+
28
+ export { Link } from './components/link'