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.
- package/README.md +34 -12
- package/package.json +9 -3
- package/src/cli.ts +10 -7
- package/src/commands/new.ts +172 -0
- package/src/commands/templates/pages/.editorconfig +21 -0
- package/src/commands/templates/pages/README.md +21 -0
- package/src/commands/templates/pages/_gitignore +24 -0
- package/src/commands/templates/pages/components/locale-select.tsx +59 -0
- package/src/commands/templates/pages/components/select.tsx +95 -0
- package/src/commands/templates/pages/i18n/en.ts +17 -0
- package/src/commands/templates/pages/i18n/index.ts +19 -0
- package/src/commands/templates/pages/i18n/pt-br.ts +17 -0
- package/src/commands/templates/pages/package.json +22 -0
- package/src/commands/templates/pages/pages/404.tsx +12 -0
- package/src/commands/templates/pages/pages/index.tsx +16 -0
- package/src/commands/templates/pages/pages/layout.tsx +24 -0
- package/src/commands/templates/pages/style.css +24 -0
- package/src/commands/templates/pages/tsconfig.json +54 -0
- package/src/commands/templates/pages/types.ts +8 -0
- package/src/commands/templates/server/base/.editorconfig +21 -0
- package/src/commands/templates/server/base/.env.dev.example +2 -0
- package/src/commands/templates/server/base/.env.prod.example +2 -0
- package/src/commands/templates/server/base/README.md +29 -0
- package/src/commands/templates/server/base/_gitignore +100 -0
- package/src/commands/templates/server/base/actions/blog/index.get.ts +9 -0
- package/src/commands/templates/server/base/actions/blog/post/[id].get.ts +9 -0
- package/src/commands/templates/server/base/actions/index.get.ts +5 -0
- package/src/commands/templates/server/base/configs/duto.ts +11 -0
- package/src/commands/templates/server/base/configs/roles.ts +5 -0
- package/src/commands/templates/server/base/package.json +24 -0
- package/src/commands/templates/server/base/tsconfig.json +42 -0
- package/src/commands/templates/server/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 +19 -6
- package/src/pages/{commands → cli/commands}/preview.ts +6 -4
- package/src/pages/cli/index.ts +10 -0
- package/src/pages/cli/utils.ts +126 -0
- package/src/pages/client/app.tsx +27 -74
- package/src/pages/client/router.ts +15 -281
- package/src/pages/compiler/aliases.ts +2 -8
- package/src/pages/compiler/ast.ts +1 -538
- package/src/pages/compiler/constants.ts +95 -13
- package/src/pages/compiler/file.ts +1 -1
- package/src/pages/compiler/index.ts +20 -128
- package/src/pages/compiler/meta.ts +39 -228
- package/src/pages/compiler/routes.ts +4 -5
- package/src/pages/compiler/types.ts +11 -101
- package/src/pages/compiler/vite-plugin.ts +90 -69
- package/src/pages/i18n/client.ts +19 -7
- package/src/pages/i18n/element.ts +1 -1
- package/src/pages/i18n/server.ts +22 -7
- package/src/pages/index.ts +1 -2
- 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 +8 -31
- package/src/server/utils.ts +25 -0
- package/src/utils.ts +43 -2
- package/src/pages/commands/dev-old.ts +0 -213
- package/src/pages/compiler/island.ts +0 -108
- package/src/pages/compiler/utils.ts +0 -5
- package/src/server/http.ts +0 -23
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
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process'
|
|
2
|
-
import { Envir } from 't0n'
|
|
3
2
|
import { command } from 't0n/cli'
|
|
4
3
|
import { error } from 't0n/log'
|
|
5
4
|
import { getRuntime } from 't0n/cli'
|
|
@@ -28,7 +27,7 @@ export default command({
|
|
|
28
27
|
},
|
|
29
28
|
},
|
|
30
29
|
async run({ args }) { // @ts-ignore
|
|
31
|
-
const platform = normalizePlatform(args.p || args.platform || args._[0] ||
|
|
30
|
+
const platform = normalizePlatform(args.p || args.platform || args._[0] || getEnv('duto.platform'))
|
|
32
31
|
if (!platform)
|
|
33
32
|
return platformError()
|
|
34
33
|
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from '../utils'
|
|
17
17
|
import { _root } from '@/utils'
|
|
18
18
|
import { withPort } from 't0n/port'
|
|
19
|
-
import {
|
|
19
|
+
import { getEnv } from 't0n'
|
|
20
20
|
import { $dev, setEnv } from '$/utils/environment'
|
|
21
21
|
|
|
22
22
|
export default command({
|
|
@@ -50,13 +50,15 @@ export default command({
|
|
|
50
50
|
},
|
|
51
51
|
async run({ args }) {
|
|
52
52
|
setEnv($dev)
|
|
53
|
-
const duto =
|
|
53
|
+
const duto = getEnv('duto', {})
|
|
54
54
|
const platform = normalizePlatform(args.p || args.platform || duto.platform || args._[0] || 'node')
|
|
55
55
|
if (!platform)
|
|
56
56
|
return platformError()
|
|
57
57
|
|
|
58
|
-
const desiredPort =
|
|
59
|
-
const host =
|
|
58
|
+
const desiredPort = Number(args.port || duto?.dev?.port || 3000)
|
|
59
|
+
const host = String(args.host || duto?.dev?.host || 'localhost')
|
|
60
|
+
// const desiredPort = args.port ? Number(args.port) : duto?.dev?.port || 3000
|
|
61
|
+
// const host = args.host ? String(args.host) : duto?.dev?.host || 'localhost'
|
|
60
62
|
|
|
61
63
|
let isBuilding = false
|
|
62
64
|
const startApp = async (start: Function, stop: Function|undefined = undefined, building: boolean = true) => {
|
package/src/server/cli/utils.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { mkdirSync, existsSync, statSync, readdirSync, rmSync, unlinkSync, copyF
|
|
|
4
4
|
import { stat } from 'node:fs/promises'
|
|
5
5
|
import { basename, dirname, join } from 'pathe'
|
|
6
6
|
import { createHash, createHmac } from 'node:crypto'
|
|
7
|
-
import { filesize } from 'filesize'
|
|
8
7
|
|
|
9
8
|
import { findWranglerConfig, parseWranglerConfig, WRANGLER_CONFIG_FILES } from 'localflare-core'
|
|
10
9
|
import type { WranglerConfig, LocalflareManifest } from 'localflare-core'
|
|
@@ -13,7 +12,7 @@ import { gray, bold, italic, purple, yellow, red } from 't0n/color'
|
|
|
13
12
|
import { substep, event, error, warn } from 't0n/log'
|
|
14
13
|
|
|
15
14
|
import { cacheRoutes } from '$/routes'
|
|
16
|
-
import {
|
|
15
|
+
import { _root, _server, filesize } from '@/utils'
|
|
17
16
|
|
|
18
17
|
import type { Platform } from './types'
|
|
19
18
|
|
|
@@ -137,17 +136,12 @@ export const build = async ({
|
|
|
137
136
|
if (!silent) event('Routes cached')
|
|
138
137
|
|
|
139
138
|
const result = await Bun.build({
|
|
140
|
-
entrypoints: [join(
|
|
139
|
+
entrypoints: [join(_server, 'adapter', `${platform}.ts`)],
|
|
141
140
|
outdir,
|
|
142
141
|
format: 'esm',
|
|
143
142
|
target: 'bun',
|
|
144
143
|
conditions: isWorkerd ? ['worker', 'browser'] : [],
|
|
145
144
|
minify: !!minify,
|
|
146
|
-
// minify: {
|
|
147
|
-
// whitespace: true,
|
|
148
|
-
// syntax: true,
|
|
149
|
-
// identifiers: true,
|
|
150
|
-
// },
|
|
151
145
|
|
|
152
146
|
treeShaking: true,
|
|
153
147
|
legalComments: 'none',
|
package/src/server/config.ts
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
import { DataBag } from 't0n'
|
|
2
1
|
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { get, set } from 't0n'
|
|
3
|
+
|
|
4
|
+
const obj: Record<string, unknown> = {}
|
|
5
|
+
|
|
6
|
+
export function getConfig<T = unknown>(key: string, defaultValue: T): T
|
|
7
|
+
export function getConfig<T = unknown>(key: string, defaultValue?: T): T | undefined
|
|
8
|
+
export function getConfig<T = unknown>(key: string, defaultValue?: T) {
|
|
9
|
+
return get<T>(obj, key, defaultValue)
|
|
10
|
+
}
|
|
11
|
+
export const setConfig = (key: string, val: unknown) => set(obj, key, val)
|
|
12
|
+
export function addConfig<T = unknown>(data: Record<string, T>) {
|
|
13
|
+
Object.assign(obj, data)
|
|
14
|
+
}
|
|
15
|
+
// export const getConfig = <T = unknown>(key: string, defaultValue?: T) => get<T>(obj, key, defaultValue)
|
|
16
|
+
// import { DataBag } from 't0n'
|
|
17
|
+
|
|
18
|
+
// const Config = new DataBag()
|
|
19
|
+
// export default Config
|
package/src/server/entry.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getConfig } from '$/config'
|
|
2
2
|
import { registerOpenAPI } from '$/open-api/register'
|
|
3
3
|
import { Ability } from '$/auth'
|
|
4
4
|
import $ from '$/app'
|
|
@@ -10,10 +10,10 @@ import { routes, middlewares } from '.duto/imports.mjs'
|
|
|
10
10
|
|
|
11
11
|
// @ts-ignore
|
|
12
12
|
Ability.fromRoutes(routes)
|
|
13
|
-
Ability.roles =
|
|
13
|
+
Ability.roles = getConfig('roles', {})
|
|
14
14
|
|
|
15
15
|
// @ts-ignore
|
|
16
16
|
const app = $({ routes, middlewares })
|
|
17
|
-
registerOpenAPI(app,
|
|
17
|
+
registerOpenAPI(app, getConfig('duto.docs', {}))
|
|
18
18
|
|
|
19
19
|
export { app }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { basicAuth } from 'hono/basic-auth'
|
|
2
2
|
import response from '$/response'
|
|
3
|
-
import
|
|
3
|
+
import { getConfig } from '$/config'
|
|
4
4
|
import type { Hono } from '$/types'
|
|
5
5
|
|
|
6
6
|
export function registerOpenAPI(app: Hono, opts: any) {
|
|
@@ -24,6 +24,6 @@ export function registerOpenAPI(app: Hono, opts: any) {
|
|
|
24
24
|
})
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
app.get(opts.path, async () => response.html(
|
|
28
|
-
app.get(opts.path +'/openapi', async () => response.raw(200,
|
|
27
|
+
app.get(opts.path, async () => response.html(getConfig('DUTO_OAC')))
|
|
28
|
+
app.get(opts.path +'/openapi', async () => response.raw(200, getConfig('DUTO_OAS'), 'application/json'))
|
|
29
29
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { STATUS_CODES } from 'node:http'
|
|
2
2
|
import { generateSpecs, resolver } from 'hono-openapi'
|
|
3
3
|
import { array, object, string } from 'zod/mini'
|
|
4
|
-
import {
|
|
4
|
+
import { getEnv } from 't0n'
|
|
5
5
|
import { Scalar } from '@scalar/hono-api-reference'
|
|
6
6
|
import { minify } from '@minify-html/node'
|
|
7
7
|
import type { Hono } from '$/types'
|
|
@@ -14,8 +14,8 @@ export function openAPIConfig(opts: any) {
|
|
|
14
14
|
agent = false,
|
|
15
15
|
name = '',
|
|
16
16
|
title = '',
|
|
17
|
-
version =
|
|
18
|
-
description =
|
|
17
|
+
version = getEnv('APP_VERSION') || getEnv('VERSION_HASH') || '1.0.0',
|
|
18
|
+
description = getEnv('APP_DESCRIPTION', ''),
|
|
19
19
|
auth = {},
|
|
20
20
|
...docs
|
|
21
21
|
} = opts?.docs ?? {}
|
|
@@ -25,7 +25,7 @@ export function openAPIConfig(opts: any) {
|
|
|
25
25
|
path,
|
|
26
26
|
auth,
|
|
27
27
|
agent: !!agent,
|
|
28
|
-
name: name || title ||
|
|
28
|
+
name: name || title || getEnv('APP_NAME', 'API Docs'),
|
|
29
29
|
version,
|
|
30
30
|
desc: description,
|
|
31
31
|
...docs,
|
|
@@ -91,6 +91,13 @@ export async function generateOpenAPIClient(app: Hono, opts?: any) {
|
|
|
91
91
|
// onLoaded: () => document?.querySelectorAll('[href="https://www.scalar.com"]')?.forEach(el => el.remove()),
|
|
92
92
|
// favicon: 'https://example.com/favicon.png',
|
|
93
93
|
// hideDownloadButton: true,
|
|
94
|
+
defaultHttpClient: {
|
|
95
|
+
targetKey: 'shell',
|
|
96
|
+
clientKey: 'curl',
|
|
97
|
+
},
|
|
98
|
+
hiddenClients: [
|
|
99
|
+
'c', 'clojure', 'csharp', 'dart', 'fsharp', 'go', 'http', 'java', 'julia', 'kotlin', 'node', 'objc', 'ocaml', 'php', 'python', 'powershell', 'r', 'ruby', 'rust', 'swift'
|
|
100
|
+
],
|
|
94
101
|
})
|
|
95
102
|
)
|
|
96
103
|
|
package/src/server/request.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCookie, getSignedCookie, setCookie, setSignedCookie, deleteCookie } from 'hono/cookie'
|
|
2
2
|
import { HTTPException } from 'hono/http-exception'
|
|
3
3
|
import { Authnz, Token } from './auth'
|
|
4
|
-
import {
|
|
4
|
+
import { addEnv } from 't0n'
|
|
5
5
|
|
|
6
6
|
import type { Context } from 'hono'
|
|
7
7
|
import { routePath, matchedRoutes } from 'hono/route'
|
|
@@ -10,21 +10,52 @@ import type { CookieOptions, CookiePrefixOptions } from 'hono/utils/cookie'
|
|
|
10
10
|
import type { CustomHeader, RequestHeader } from 'hono/utils/headers'
|
|
11
11
|
import type { BodyData, ParseBodyOptions } from 'hono/utils/body'
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
// function cookieWrapper(c: Context) {
|
|
14
|
+
// return {
|
|
15
|
+
// all: () => getCookie(c),
|
|
16
|
+
// allSigned: (secret: string) => getSignedCookie(c, secret),
|
|
17
|
+
// get: (name: string, prefixOptions?: CookiePrefixOptions) => prefixOptions ? getCookie(c, name, prefixOptions) : getCookie(c, name),
|
|
18
|
+
// getSigned: (secret: string, name: string, prefixOptions?: CookiePrefixOptions) => prefixOptions ? getSignedCookie(c, secret, name, prefixOptions) : getSignedCookie(c, secret, name),
|
|
19
|
+
// set: (name: string, value: string, opt?: CookieOptions) => setCookie(c, name, value, opt),
|
|
20
|
+
// setSigned: (name: string, value: string, secret: string, opt?: CookieOptions) => setSignedCookie(c, name, value, secret, opt),
|
|
21
|
+
// delete: (name: string, opt?: CookieOptions) => deleteCookie(c, name, opt)
|
|
22
|
+
// }
|
|
23
|
+
// }
|
|
24
|
+
class $Cookie {
|
|
25
|
+
#c!: Context
|
|
26
|
+
constructor(c: Context) {
|
|
27
|
+
this.#c = c
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
all() {
|
|
31
|
+
return getCookie(this.#c)
|
|
32
|
+
}
|
|
33
|
+
allSigned(secret: string) {
|
|
34
|
+
return getSignedCookie(this.#c, secret)
|
|
35
|
+
}
|
|
36
|
+
get(name: string, prefixOptions?: CookiePrefixOptions) {
|
|
37
|
+
return prefixOptions ? getCookie(this.#c, name, prefixOptions) : getCookie(this.#c, name)
|
|
38
|
+
}
|
|
39
|
+
getSigned(secret: string, name: string, prefixOptions?: CookiePrefixOptions) {
|
|
40
|
+
return prefixOptions ? getSignedCookie(this.#c, secret, name, prefixOptions) : getSignedCookie(this.#c, secret, name)
|
|
41
|
+
}
|
|
42
|
+
set(name: string, value: string, opt?: CookieOptions) {
|
|
43
|
+
setCookie(this.#c, name, value, opt)
|
|
44
|
+
}
|
|
45
|
+
setSigned(name: string, value: string, secret: string, opt?: CookieOptions) {
|
|
46
|
+
setSignedCookie(this.#c, name, value, secret, opt)
|
|
47
|
+
}
|
|
48
|
+
delete(name: string, opt?: CookieOptions) {
|
|
49
|
+
deleteCookie(this.#c, name, opt)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
22
52
|
|
|
23
53
|
export const GET_REQUEST: unique symbol = Symbol()
|
|
24
54
|
|
|
25
55
|
export default class $Request {
|
|
26
56
|
#c!: Context
|
|
27
|
-
#cookie:
|
|
57
|
+
#cookie: $Cookie
|
|
58
|
+
// #cookie: ReturnType<typeof cookieWrapper>
|
|
28
59
|
#u: Authnz<any> | null = null
|
|
29
60
|
|
|
30
61
|
#host: string
|
|
@@ -34,7 +65,8 @@ export default class $Request {
|
|
|
34
65
|
|
|
35
66
|
constructor(c: Context) {
|
|
36
67
|
this.#c = c
|
|
37
|
-
this.#cookie =
|
|
68
|
+
this.#cookie = new $Cookie(c)
|
|
69
|
+
// this.#cookie = cookieWrapper(c)
|
|
38
70
|
|
|
39
71
|
const url = new URL(c.req.raw.url)
|
|
40
72
|
this.#host = url.protocol +'//'+ url.host
|
|
@@ -47,11 +79,11 @@ export default class $Request {
|
|
|
47
79
|
const req = new $Request(c)
|
|
48
80
|
await req.setAuth()
|
|
49
81
|
c.set(GET_REQUEST as unknown as string, req)
|
|
50
|
-
if (c.env)
|
|
82
|
+
if (c.env) addEnv(c.env)
|
|
51
83
|
}
|
|
52
84
|
|
|
53
85
|
async setAuth() {
|
|
54
|
-
this.#u = Authnz.fromToken(Token.fromRequest(this))
|
|
86
|
+
this.#u = Authnz.fromToken(await Token.fromRequest(this))
|
|
55
87
|
}
|
|
56
88
|
|
|
57
89
|
get user() {
|
package/src/server/routes.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { file, write } from 'bun'
|
|
2
2
|
|
|
3
3
|
import { copyFileSync } from 'node:fs'
|
|
4
4
|
import { join, relative } from 'pathe'
|
|
@@ -12,38 +12,15 @@ import { STATUS_CODES } from 'node:http'
|
|
|
12
12
|
import $ from './app'
|
|
13
13
|
import _response from './response'
|
|
14
14
|
import _validator from './validator'
|
|
15
|
-
import { _root,
|
|
16
|
-
import { getLastCommitHash, ensureDir, nextId } from './utils'
|
|
15
|
+
import { _root, _server, scan } from '@/utils'
|
|
16
|
+
import { getLastCommitHash, ensureDir, nextId, verbAlias } from './utils'
|
|
17
17
|
import { generateOpenAPI, generateOpenAPIClient, openAPIConfig } from './open-api/spec'
|
|
18
|
-
import { verbAlias } from './http'
|
|
19
18
|
import { highlightedMethod, highlightedURI } from './cli/utils'
|
|
20
19
|
|
|
21
20
|
import type { Routes, Rule, StandardSchemaV1 } from './types'
|
|
22
21
|
import { autorizedPath } from './middlewares/auth'
|
|
23
22
|
import { isDev } from './utils/environment'
|
|
24
23
|
|
|
25
|
-
export async function* scan(
|
|
26
|
-
dir: string | string[],
|
|
27
|
-
ext: string | string[],
|
|
28
|
-
ignore: string[] = ['*.d.*'],
|
|
29
|
-
cwd?: string,
|
|
30
|
-
): AsyncGenerator<[string, string, any]> {
|
|
31
|
-
if (typeof dir !== 'string')
|
|
32
|
-
dir = ext.length === 1 ? dir[0] : `{${dir.join(',')}}`
|
|
33
|
-
|
|
34
|
-
if (typeof ext !== 'string')
|
|
35
|
-
ext = ext.length === 1 ? ext[0] : `{${ext.join(',')}}`
|
|
36
|
-
|
|
37
|
-
cwd ??= _root
|
|
38
|
-
for await (const file of new Glob(dir +'/**/*.'+ ext).scan({
|
|
39
|
-
cwd,
|
|
40
|
-
absolute: true,
|
|
41
|
-
onlyFiles: true, // @ts-ignore
|
|
42
|
-
ignore,
|
|
43
|
-
})) {
|
|
44
|
-
yield [file, file.split(cwd as string)[1], await IMPORT(file)]
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
24
|
|
|
48
25
|
const importName = (name: string | undefined, dirs: string[]) => (name || nextId()).replace(/\.ts$/, '')
|
|
49
26
|
|
|
@@ -406,12 +383,12 @@ export async function cacheRoutes() {
|
|
|
406
383
|
const configs = await getConfigs()
|
|
407
384
|
const middlewares = await getMiddlewares()
|
|
408
385
|
if (isDev()) {
|
|
409
|
-
const _file = join(
|
|
386
|
+
const _file = join(_server, 'middlewares', 'logger.ts')
|
|
410
387
|
const _mod = await IMPORT(_file) // @ts-ignore
|
|
411
|
-
middlewares.unshift({
|
|
388
|
+
middlewares.unshift({ // @ts-ignore
|
|
412
389
|
path: _mod?.path || '*',
|
|
413
390
|
name: 'dev_logger',
|
|
414
|
-
file: _file,
|
|
391
|
+
file: _file, // @ts-ignore
|
|
415
392
|
handle: _mod.handle,
|
|
416
393
|
})
|
|
417
394
|
}
|
|
@@ -447,8 +424,8 @@ export async function cacheRoutes() {
|
|
|
447
424
|
const _dutoDir = await dependencyPath('duto')
|
|
448
425
|
|
|
449
426
|
await write(iPath, `// AUTO-GENERATED FILE - DO NOT EDIT
|
|
450
|
-
${env?.length ? `import {
|
|
451
|
-
${Object.entries(configs)?.length ? `import
|
|
427
|
+
${env?.length ? `import { addEnv } from '${await dependencyPath('t0n')}/src/env'\naddEnv(${JSJSON(Object.fromEntries(env))})` : ''}
|
|
428
|
+
${Object.entries(configs)?.length ? `import { addConfig } from '${_dutoDir}/src/server/config'\naddConfig(${JSJSON(configs)})` : ''}
|
|
452
429
|
|
|
453
430
|
${middlewares.map(r => `import { handle as MW${r.name} } from '../${normalizeImportPath(r.file)}'`).join('\n')}
|
|
454
431
|
export const middlewares = [[${middlewares.map(mw => [
|
package/src/server/utils.ts
CHANGED
|
@@ -44,3 +44,28 @@ export const nextId = () => {
|
|
|
44
44
|
|
|
45
45
|
return id = 'a' + chars.join('')
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
export const verbAlias = {
|
|
49
|
+
get: 0,
|
|
50
|
+
post: 1,
|
|
51
|
+
put: 2,
|
|
52
|
+
patch: 3,
|
|
53
|
+
delete: 4,
|
|
54
|
+
head: 5,
|
|
55
|
+
options: 6,
|
|
56
|
+
connect: 7,
|
|
57
|
+
trace: 8,
|
|
58
|
+
} as Record<string, number>
|
|
59
|
+
|
|
60
|
+
export const getVerb = [
|
|
61
|
+
'get',
|
|
62
|
+
'post',
|
|
63
|
+
'put',
|
|
64
|
+
'patch',
|
|
65
|
+
'delete',
|
|
66
|
+
'head',
|
|
67
|
+
'options',
|
|
68
|
+
'connect',
|
|
69
|
+
'trace',
|
|
70
|
+
]
|
|
71
|
+
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IMPORT } from 't0n'
|
|
2
2
|
import { dirname, join } from 'pathe'
|
|
3
3
|
|
|
4
4
|
export const _duto = dirname(new URL(import.meta.url).pathname)
|
|
5
|
-
export const
|
|
5
|
+
export const _pages = join(_duto, 'pages')
|
|
6
|
+
export const _server = join(_duto, 'server') //@ts-ignore
|
|
7
|
+
export const _root = process.env?.npm_config_local_prefix || process.env?.PWD || process.stdin?.path || process.cwd() // || join(_duto, '../../')s
|
|
8
|
+
|
|
9
|
+
const UNITS = ['B', 'kB', 'MB', 'GB']
|
|
10
|
+
export function filesize(bytes: number, decimals = 2) {
|
|
11
|
+
if (!Number.isFinite(bytes) || bytes <= 0) return '0 B'
|
|
12
|
+
|
|
13
|
+
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), UNITS.length - 1)
|
|
14
|
+
return `${parseFloat((bytes / 1024 ** i).toFixed(decimals))} ${UNITS[i]}`
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const formatTime = (ms: number) => {
|
|
18
|
+
if (ms < 0.001) return `${(ms * 1_000_000).toFixed(2)}ns`
|
|
19
|
+
if (ms < 1) return `${(ms * 1000).toFixed(2)}µs`
|
|
20
|
+
if (ms < 1000) return `${ms.toFixed(2)}ms`
|
|
21
|
+
if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`
|
|
22
|
+
return `${Math.floor(ms / 60000)}m ${((ms % 60000) / 1000).toFixed(1)}s`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function* scan(
|
|
26
|
+
dir: string | string[],
|
|
27
|
+
ext: string | string[],
|
|
28
|
+
ignore: string[] = ['*.d.*'],
|
|
29
|
+
cwd?: string,
|
|
30
|
+
): AsyncGenerator<[string, string, any]> {
|
|
31
|
+
if (typeof dir !== 'string')
|
|
32
|
+
dir = ext.length === 1 ? dir[0] : `{${dir.join(',')}}`
|
|
33
|
+
|
|
34
|
+
if (typeof ext !== 'string')
|
|
35
|
+
ext = ext.length === 1 ? ext[0] : `{${ext.join(',')}}`
|
|
36
|
+
|
|
37
|
+
cwd ??= _root
|
|
38
|
+
for await (const file of new Bun.Glob(dir +'/**/*.'+ ext).scan({
|
|
39
|
+
cwd,
|
|
40
|
+
absolute: true,
|
|
41
|
+
onlyFiles: true, // @ts-ignore
|
|
42
|
+
ignore,
|
|
43
|
+
})) {
|
|
44
|
+
yield [file, file.split(cwd as string)[1], await IMPORT(file)]
|
|
45
|
+
}
|
|
46
|
+
}
|