duto 0.260906.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.
- package/README.md +34 -12
- package/package.json +9 -3
- package/src/cli.ts +10 -7
- package/src/commands/new.ts +147 -0
- package/src/commands/templates/base/.editorconfig +21 -0
- package/src/commands/templates/base/.env.dev.example +2 -0
- package/src/commands/templates/base/.env.prod.example +2 -0
- package/src/commands/templates/base/README.md +29 -0
- package/src/commands/templates/base/_gitignore +100 -0
- package/src/commands/templates/base/actions/blog/index.get.ts +9 -0
- package/src/commands/templates/base/actions/blog/post/[id].get.ts +9 -0
- package/src/commands/templates/base/actions/index.get.ts +5 -0
- package/src/commands/templates/base/configs/duto.ts +11 -0
- package/src/commands/templates/base/configs/roles.ts +5 -0
- package/src/commands/templates/base/package.json +24 -0
- package/src/commands/templates/base/tsconfig.json +42 -0
- package/src/commands/templates/workerd/wrangler.toml +47 -0
- package/src/commands/upgrade.ts +30 -0
- package/src/index.ts +7 -2
- package/src/pages/{commands → cli/commands}/build.ts +13 -7
- package/src/pages/{commands → cli/commands}/dev.ts +11 -4
- package/src/pages/{commands → cli/commands}/preview.ts +6 -4
- package/src/pages/cli/index.ts +10 -0
- package/src/pages/cli/utils.ts +145 -0
- package/src/pages/client/app.tsx +1 -1
- package/src/pages/client/router.ts +1 -1
- package/src/pages/compiler/file.ts +1 -1
- package/src/pages/compiler/index.ts +2 -4
- package/src/pages/compiler/meta.ts +2 -2
- package/src/pages/compiler/routes.ts +1 -1
- package/src/pages/compiler/types.ts +10 -0
- package/src/pages/compiler/vite-plugin.ts +19 -44
- package/src/pages/i18n/client.ts +1 -1
- package/src/pages/i18n/element.ts +1 -1
- package/src/pages/i18n/server.ts +1 -1
- package/src/pages/preact/server.ts +1 -1
- package/src/server/app.ts +5 -10
- package/src/server/auth/ability.ts +1 -1
- package/src/server/auth/token.ts +5 -5
- package/src/server/cli/commands/build.ts +2 -2
- package/src/server/cli/commands/deploy.ts +1 -2
- package/src/server/cli/commands/dev.ts +6 -4
- package/src/server/cli/commands/routes.ts +0 -1
- package/src/server/cli/utils.ts +2 -8
- package/src/server/config.ts +18 -3
- package/src/server/entry.ts +3 -3
- package/src/server/open-api/register.ts +3 -3
- package/src/server/open-api/spec.ts +11 -4
- package/src/server/request.ts +46 -14
- package/src/server/routes.ts +5 -6
- package/src/server/utils.ts +25 -0
- package/src/utils.ts +12 -2
- package/src/pages/commands/dev-old.ts +0 -213
- package/src/pages/compiler/utils.ts +0 -5
- package/src/server/http.ts +0 -23
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
import { build } from 'vite'
|
|
2
|
-
import {
|
|
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 '
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
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
|
-
|
|
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 '
|
|
5
|
+
import { getMetadata } from '#/compiler/meta'
|
|
6
6
|
import { _root } from '@/utils'
|
|
7
|
-
import { getConfig, preview, reload } from '
|
|
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
|
-
|
|
32
|
-
const
|
|
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 '
|
|
5
|
+
import { getMetadata } from '#/compiler/meta'
|
|
6
6
|
import { _root } from '@/utils'
|
|
7
7
|
import { args } from './dev'
|
|
8
|
-
import { getConfig, preview } from '
|
|
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
|
-
|
|
19
|
-
|
|
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,145 @@
|
|
|
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
|
+
|
|
12
|
+
export async function getConfig(name = 'config'): Promise<UserConfig & PluginOptions> {
|
|
13
|
+
let opts = {} as UserConfig
|
|
14
|
+
const file = resolveExtension(name)
|
|
15
|
+
if (file) opts = await IMPORT(join(_root, file), 'default')
|
|
16
|
+
return config(opts)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// export const formatTime = (ms: number) => {
|
|
20
|
+
// if (ms < 1000) return `${ms}ms`
|
|
21
|
+
// return `${(ms / 1000).toFixed(2)}s`
|
|
22
|
+
// }
|
|
23
|
+
export const formatTime = (ms: number) => {
|
|
24
|
+
if (ms < 0.001) return `${(ms * 1_000_000).toFixed(2)}ns`
|
|
25
|
+
if (ms < 1) return `${(ms * 1000).toFixed(2)}µs`
|
|
26
|
+
if (ms < 1000) return `${ms.toFixed(2)}ms`
|
|
27
|
+
if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`
|
|
28
|
+
return `${Math.floor(ms / 60000)}m ${((ms % 60000) / 1000).toFixed(1)}s`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const statusColorMap = new Map([
|
|
32
|
+
[5, red],
|
|
33
|
+
[4, yellow],
|
|
34
|
+
[3, cyan],
|
|
35
|
+
])
|
|
36
|
+
|
|
37
|
+
const getStatusColor = (status: number) => (statusColorMap.get(Math.floor(status / 100)) ?? green)(String(status))
|
|
38
|
+
|
|
39
|
+
const clients = new Set<Bun.ServerWebSocket<void>>()
|
|
40
|
+
export function reload() {
|
|
41
|
+
for (const ws of clients) {
|
|
42
|
+
if (ws.readyState === WebSocket.OPEN)
|
|
43
|
+
ws.send('reload')
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function preview(
|
|
48
|
+
meta: Metadata,
|
|
49
|
+
host: string = '0.0.0.0',
|
|
50
|
+
port: number = 4173
|
|
51
|
+
) {
|
|
52
|
+
return Bun.serve({
|
|
53
|
+
hostname: host,
|
|
54
|
+
port,
|
|
55
|
+
|
|
56
|
+
websocket: {
|
|
57
|
+
open(ws) {
|
|
58
|
+
clients.add(ws)
|
|
59
|
+
},
|
|
60
|
+
close(ws) {
|
|
61
|
+
clients.delete(ws)
|
|
62
|
+
},
|
|
63
|
+
message() {},
|
|
64
|
+
},
|
|
65
|
+
async fetch(req, server) {
|
|
66
|
+
const start = performance.now()
|
|
67
|
+
|
|
68
|
+
const url = new URL(req.url)
|
|
69
|
+
const path = decodeURIComponent(url.pathname)
|
|
70
|
+
const headers = {
|
|
71
|
+
'Access-Control-Allow-Origin': '*',
|
|
72
|
+
'Access-Control-Allow-Methods': 'GET',
|
|
73
|
+
'Access-Control-Allow-Headers': '*',
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (req.method === 'OPTIONS')
|
|
77
|
+
return new Response(null, { status: 204, headers })
|
|
78
|
+
|
|
79
|
+
if (req.headers.get('upgrade') === 'websocket'
|
|
80
|
+
&& req.headers.get('sec-websocket-protocol') === 'duto') {
|
|
81
|
+
server.upgrade(req)
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let status = 500
|
|
86
|
+
let route: string | undefined
|
|
87
|
+
let matched: Bun.MatchedRoute | null | undefined
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
let res: Response
|
|
91
|
+
const dist = 'dist' // TODO: get from configs
|
|
92
|
+
|
|
93
|
+
let file = Bun.file(join(_root, dist, path))
|
|
94
|
+
|
|
95
|
+
if (await file.exists()) {
|
|
96
|
+
// route = path
|
|
97
|
+
res = new Response(file)
|
|
98
|
+
} else {
|
|
99
|
+
matched = match(path)
|
|
100
|
+
|
|
101
|
+
// console.log(matched)
|
|
102
|
+
route = matched?.name || match404(meta, path)
|
|
103
|
+
|
|
104
|
+
res = new Response(null, { status: 404 })
|
|
105
|
+
|
|
106
|
+
// for (const asset of path !== '/' && matched && matched.kind === 'exact' ? [
|
|
107
|
+
// path,
|
|
108
|
+
// join(path, 'index'),
|
|
109
|
+
// ] : ['index']) {
|
|
110
|
+
for (const asset of [
|
|
111
|
+
path,
|
|
112
|
+
join(path, 'index'),
|
|
113
|
+
'index',
|
|
114
|
+
]) {
|
|
115
|
+
file = Bun.file(join(_root, dist, asset +'.html'))
|
|
116
|
+
|
|
117
|
+
if (await file.exists()) {
|
|
118
|
+
// if (route === '/' || !route) route = asset
|
|
119
|
+
res = new Response(file)
|
|
120
|
+
break
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
status = res.status
|
|
126
|
+
return res
|
|
127
|
+
} catch (err) {
|
|
128
|
+
status = 500
|
|
129
|
+
throw err
|
|
130
|
+
} finally {
|
|
131
|
+
if (route || matched) {
|
|
132
|
+
const elapsed = `${Math.max(1, Math.ceil(performance.now() - start))}ms`
|
|
133
|
+
|
|
134
|
+
console.log([
|
|
135
|
+
gray(Datte.dateTime()),
|
|
136
|
+
getStatusColor(status),
|
|
137
|
+
path,
|
|
138
|
+
route && route !== path ? gray(route) : '',
|
|
139
|
+
gray(elapsed),
|
|
140
|
+
].filter(Boolean).join(' '))
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
})
|
|
145
|
+
}
|
package/src/pages/client/app.tsx
CHANGED
|
@@ -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 '
|
|
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 '
|
|
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,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,
|
|
3
|
+
import { existsSync, rmSync } from 'node:fs'
|
|
4
4
|
import { join } from 'node:path'
|
|
5
5
|
import { defineConfig } from 'vite'
|
|
6
6
|
|
|
@@ -13,7 +13,6 @@ 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 {
|
|
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
|
-
|
|
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 =
|
|
150
|
-
conf.build.cssMinify =
|
|
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:
|
|
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(
|
|
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') &&
|
|
222
|
-
return join(
|
|
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
|
},
|
package/src/pages/i18n/client.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h, type JSX } from 'preact'
|
|
2
|
-
import { local } from '#/storage'
|
|
2
|
+
import { local } from '#/client/storage'
|
|
3
3
|
import { navigate } from '..'
|
|
4
4
|
|
|
5
5
|
const accepted = (lang: string | undefined, locales: string[] = [], fallback: string) => lang && locales.includes(lang) ? lang : fallback
|
package/src/pages/i18n/server.ts
CHANGED
|
@@ -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 '
|
|
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) {
|
|
@@ -8,7 +8,7 @@ import { getContext, incrementIslandId } from './context'
|
|
|
8
8
|
import { restoreSignalsOnProps, serializeSignals } from './signals'
|
|
9
9
|
import StaticHtml from './static-html'
|
|
10
10
|
import type { IslandAttrs } from './types'
|
|
11
|
-
import type { IslandMeta } from '
|
|
11
|
+
import type { IslandMeta } from '#/compiler/types'
|
|
12
12
|
// import type { AstroPreactAttrs, RendererContext } from './types.js'
|
|
13
13
|
// import { createFilter } from '@astrojs/internal-helpers/create-filter'
|
|
14
14
|
|
package/src/server/app.ts
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { Hono } from 'hono'
|
|
2
|
-
import { Envir } from 't0n'
|
|
3
2
|
import type {
|
|
4
3
|
Env, Context, Next,
|
|
5
4
|
HTTPResponseError,
|
|
6
5
|
ServerOptions, Route
|
|
7
6
|
} from './types'
|
|
8
|
-
import request
|
|
7
|
+
import request from './request'
|
|
9
8
|
import response from './response'
|
|
10
9
|
import { isDev } from './utils/environment'
|
|
11
|
-
import { getVerb } from './
|
|
10
|
+
import { getVerb } from './utils'
|
|
12
11
|
import { registerMiddleware, resolveHandle, resolveMw } from './handle'
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
const EHandler = async (e: Error | HTTPResponseError) => {
|
|
13
|
+
async function EHandler(e: Error | HTTPResponseError) {
|
|
16
14
|
console.error(e)
|
|
17
15
|
|
|
18
16
|
switch (true) {
|
|
@@ -59,7 +57,7 @@ const EHandler = async (e: Error | HTTPResponseError) => {
|
|
|
59
57
|
// stack: isDev (? e.stack : undefined
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
export
|
|
60
|
+
export default function createApp<E extends Env>(options?: ServerOptions<E>) {
|
|
63
61
|
// const root = options?.root ?? '/'
|
|
64
62
|
const app = options?.app ?? new Hono<E>()
|
|
65
63
|
|
|
@@ -76,8 +74,7 @@ export const createApp = <E extends Env>(options?: ServerOptions<E>) => {
|
|
|
76
74
|
|
|
77
75
|
// @ts-ignore
|
|
78
76
|
app.onError(options?.onError || EHandler)
|
|
79
|
-
|
|
80
|
-
app.notFound(options?.notFound || NFHandler)
|
|
77
|
+
app.notFound(options?.notFound || response.notFound)
|
|
81
78
|
|
|
82
79
|
if (options?.init) options.init(app)
|
|
83
80
|
|
|
@@ -92,5 +89,3 @@ export const createApp = <E extends Env>(options?: ServerOptions<E>) => {
|
|
|
92
89
|
|
|
93
90
|
return app
|
|
94
91
|
}
|
|
95
|
-
|
|
96
|
-
export default createApp
|
package/src/server/auth/token.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { sha256,
|
|
1
|
+
import { bytesToHex, getEnv, parseUA } from 't0n'
|
|
2
|
+
import { sha256, type Config } from 'cripta'
|
|
3
3
|
import { config, create, parse } from 'cripta/token'
|
|
4
4
|
import type { IRequest } from '$/types'
|
|
5
5
|
|
|
@@ -76,12 +76,12 @@ export class Token {
|
|
|
76
76
|
if (this.#cripta)
|
|
77
77
|
return this.#cripta
|
|
78
78
|
|
|
79
|
-
return this.#cripta = await config({ key:
|
|
79
|
+
return this.#cripta = await config({ key: getEnv('KEY') })
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
static async parse(req: IRequest, token: string) {
|
|
83
83
|
const host = this.host(req)
|
|
84
|
-
const serveHost =
|
|
84
|
+
const serveHost = getEnv('FLOW_SERVER', host) as string
|
|
85
85
|
|
|
86
86
|
return parse(await this.cripta(), token, {
|
|
87
87
|
iss: serveHost,
|
|
@@ -130,7 +130,7 @@ export class Token {
|
|
|
130
130
|
static async fingerprint(req: IRequest) {
|
|
131
131
|
const ua = parseUA(req.header('user-agent'))
|
|
132
132
|
|
|
133
|
-
const id =
|
|
133
|
+
const id = bytesToHex(await sha256(
|
|
134
134
|
// (req.header('accept-language') || '')
|
|
135
135
|
this.ip(req)
|
|
136
136
|
+ ua.browser.name + ua.browser.version.split('.')[0]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getEnv } from 't0n'
|
|
2
2
|
import { command } from 't0n/cli'
|
|
3
3
|
import { gray } from 't0n/color'
|
|
4
4
|
import { wait, error, rn } from 't0n/log'
|
|
@@ -23,7 +23,7 @@ export default command({
|
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
25
|
async run({ args }) {
|
|
26
|
-
const platform = normalizePlatform(args.p || args.platform ||
|
|
26
|
+
const platform = normalizePlatform(args.p || args.platform || getEnv('duto.platform') || args._[0] || 'node')
|
|
27
27
|
if (!platform)
|
|
28
28
|
return platformError()
|
|
29
29
|
|