duto 0.0.0 → 0.260906.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 (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -12
  3. package/package.json +91 -2
  4. package/src/cli.ts +42 -0
  5. package/src/enum.ts +2 -0
  6. package/src/index.d.ts +61 -0
  7. package/src/index.ts +19 -0
  8. package/src/middleware.ts +2 -0
  9. package/src/pages/client/app.tsx +123 -0
  10. package/src/pages/client/hmr.ts +13 -0
  11. package/src/pages/client/island.ts +136 -0
  12. package/src/pages/client/link.ts +70 -0
  13. package/src/pages/client/router.ts +329 -0
  14. package/src/pages/client/storage.ts +95 -0
  15. package/src/pages/commands/build.ts +74 -0
  16. package/src/pages/commands/dev-old.ts +213 -0
  17. package/src/pages/commands/dev.ts +87 -0
  18. package/src/pages/commands/preview.ts +33 -0
  19. package/src/pages/compiler/aliases.ts +36 -0
  20. package/src/pages/compiler/assets.ts +43 -0
  21. package/src/pages/compiler/ast.ts +764 -0
  22. package/src/pages/compiler/constants.ts +24 -0
  23. package/src/pages/compiler/file.ts +60 -0
  24. package/src/pages/compiler/index.ts +307 -0
  25. package/src/pages/compiler/island.ts +108 -0
  26. package/src/pages/compiler/meta.ts +601 -0
  27. package/src/pages/compiler/routes.ts +29 -0
  28. package/src/pages/compiler/types.ts +209 -0
  29. package/src/pages/compiler/utils.ts +5 -0
  30. package/src/pages/compiler/vite-plugin.ts +324 -0
  31. package/src/pages/components/link.tsx +38 -0
  32. package/src/pages/i18n/client.ts +403 -0
  33. package/src/pages/i18n/element.ts +44 -0
  34. package/src/pages/i18n/server.ts +56 -0
  35. package/src/pages/index.ts +28 -0
  36. package/src/pages/preact/client-dev.ts +5 -0
  37. package/src/pages/preact/client.ts +87 -0
  38. package/src/pages/preact/context.ts +41 -0
  39. package/src/pages/preact/server.ts +186 -0
  40. package/src/pages/preact/signals.ts +89 -0
  41. package/src/pages/preact/static-html.ts +45 -0
  42. package/src/pages/preact/types.ts +26 -0
  43. package/src/server/adapter/aws.ts +4 -0
  44. package/src/server/adapter/workerd.ts +4 -0
  45. package/src/server/app.ts +96 -0
  46. package/src/server/auth/ability.ts +72 -0
  47. package/src/server/auth/authnz.ts +86 -0
  48. package/src/server/auth/index.ts +5 -0
  49. package/src/server/auth/token.ts +147 -0
  50. package/src/server/auth/types.ts +2 -0
  51. package/src/server/cli/commands/build.ts +41 -0
  52. package/src/server/cli/commands/deploy.ts +82 -0
  53. package/src/server/cli/commands/dev.ts +277 -0
  54. package/src/server/cli/commands/make.ts +98 -0
  55. package/src/server/cli/commands/migrate.ts +93 -0
  56. package/src/server/cli/commands/routes.ts +79 -0
  57. package/src/server/cli/index.ts +27 -0
  58. package/src/server/cli/stubs.ts +39 -0
  59. package/src/server/cli/types.ts +3 -0
  60. package/src/server/cli/utils.ts +443 -0
  61. package/src/server/config.ts +4 -0
  62. package/src/server/db/d1.d.ts +1 -0
  63. package/src/server/db/d1.ts +1 -0
  64. package/src/server/db/dynamodb.d.ts +1 -0
  65. package/src/server/db/dynamodb.ts +1 -0
  66. package/src/server/db/index.ts +1 -0
  67. package/src/server/entry.ts +19 -0
  68. package/src/server/handle.ts +30 -0
  69. package/src/server/http.ts +23 -0
  70. package/src/server/middlewares/auth.ts +40 -0
  71. package/src/server/middlewares/logger.ts +30 -0
  72. package/src/server/open-api/register.ts +29 -0
  73. package/src/server/open-api/spec.ts +107 -0
  74. package/src/server/request.ts +233 -0
  75. package/src/server/response.ts +142 -0
  76. package/src/server/routes.ts +474 -0
  77. package/src/server/types.ts +142 -0
  78. package/src/server/utils/environment.ts +17 -0
  79. package/src/server/utils.ts +46 -0
  80. package/src/server/validator.ts +70 -0
  81. package/src/utils.ts +5 -0
@@ -0,0 +1,213 @@
1
+ import { defineCommand } from 'citty'
2
+ import { build, preview } from 'vite'
3
+ import { withPort } from 't0n/port'
4
+ import { error, event, log, rn, wait } from 't0n/log'
5
+ import { getConfig } from '~/utils'
6
+ import { _root } from '@/utils'
7
+ import { watch } from 't0n/cli'
8
+ import { spawn, type ChildProcess } from 'node:child_process'
9
+
10
+ export const args = {
11
+ port: {
12
+ alias: 'p',
13
+ description: 'Port to listen on',
14
+ type: 'number',
15
+ default: 3000,
16
+ },
17
+ host: {
18
+ description: 'Host to forward requests to, defaults to the zone of project',
19
+ type: 'string',
20
+ default: 'localhost',
21
+ },
22
+ }
23
+
24
+ export default defineCommand({
25
+ meta: {
26
+ name: 'dev',
27
+ description: '🧪 Start dev server\n',
28
+ }, // @ts-ignore
29
+ args,
30
+ async run({ args }) {
31
+ const config = await getConfig()
32
+ const desiredPort = args.port ? Number(args.port) : (config?.preview?.port ? Number(config.preview.port) : 3000)
33
+ const host = args.host ? String(args.host) : (config?.preview?.host ? config.preview.host : 'localhost')
34
+
35
+ // const _build = async () => {
36
+ // return await build(await getConfig())
37
+ // }
38
+
39
+ // let buildProcess: ChildProcess | null = null
40
+ // const _build = async () => {
41
+ // if (buildProcess) await killProcess(buildProcess)
42
+
43
+ // return new Promise<void>((resolve, reject) => {
44
+ // let timeoutId: NodeJS.Timeout | null = null
45
+
46
+ // buildProcess = spawn('duto', ['build'], {
47
+ // // stdio: 'ignore',
48
+ // stdio: ['inherit', 'ignore', 'inherit', 'ipc'],
49
+ // shell: process.platform === 'win32'
50
+ // })
51
+
52
+ // buildProcess.on('close', (code) => {
53
+ // if (timeoutId) clearTimeout(timeoutId)
54
+ // buildProcess = null
55
+
56
+ // if (code === 0) {
57
+ // resolve()
58
+ // } else {
59
+ // reject(new Error(`Build failed with code ${code}`))
60
+ // }
61
+ // })
62
+
63
+ // buildProcess.on('error', (error) => {
64
+ // if (timeoutId) clearTimeout(timeoutId)
65
+ // buildProcess = null
66
+ // reject(error)
67
+ // })
68
+ // })
69
+ // }
70
+
71
+ // const killProcess = async (app: ChildProcess | null) => {
72
+ // if (!app) return null
73
+ // // event('Stopping..')
74
+ // try {
75
+ // if (!app?.killed) {
76
+ // app.kill('SIGTERM')
77
+ // await wait(1000)
78
+
79
+ // if (!app?.killed) { // force kill
80
+ // app.kill('SIGKILL')
81
+ // await wait(1000)
82
+ // }
83
+ // }
84
+
85
+ // return null
86
+ // } catch (e) {
87
+ // error('Error stopping:', e)
88
+ // }
89
+
90
+ // return null
91
+ // }
92
+
93
+ let buildProcess: Bun.Subprocess | null = null
94
+
95
+ const _build = async () => {
96
+ if (buildProcess) await killProcess(buildProcess)
97
+ buildProcess = Bun.spawn(['duto', 'build'], {stdin: 'inherit', stdout: 'ignore', stderr: 'inherit'})
98
+
99
+ try {
100
+ const code = await buildProcess.exited
101
+
102
+ if (code !== 0)
103
+ throw new Error(`Build failed with code ${code}`)
104
+ } finally {
105
+ buildProcess = null
106
+ }
107
+ }
108
+
109
+ const killProcess = async (proc: Bun.Subprocess | null) => {
110
+ if (!proc || proc.exitCode !== null) return
111
+
112
+ try {
113
+ proc.kill('SIGTERM')
114
+
115
+ const exited = await Promise.race([
116
+ proc.exited.then(() => true),
117
+ new Promise(r => setTimeout(r, 1000)).then(() => false),
118
+ ])
119
+
120
+ if (!exited && proc.exitCode === null) {
121
+ proc.kill('SIGKILL')
122
+ await proc.exited
123
+ }
124
+ } catch (e) {
125
+ error('Error stopping:', e)
126
+ }
127
+ }
128
+
129
+ withPort(desiredPort, async (port) => {
130
+ const ignore = [
131
+ /(^|[\/\\])\.(duto|git|cache|vscode|idea|next|nuxt|nyc_output)([\/\\]|$)/,
132
+ /(^|[\/\\])(node_modules|tmp|dist|build|out|coverage)([\/\\]|$)/,
133
+
134
+ /\.(DS_Store|localized|tmp|temp|log|pid|swp|swo)$/,
135
+ /(Thumbs\.db|desktop\.ini)$/,
136
+ /~$/,
137
+
138
+ /(^|[\/\\])\.(Spotlight-V100|Trashes)([\/\\]|$)/,
139
+ /(^|[\/\\])__MACOSX([\/\\]|$)/,
140
+ ]
141
+
142
+ try {
143
+ await _build()
144
+
145
+ const clients = new Set<ReadableStreamDefaultController<string>>()
146
+ const reload = () => {
147
+ for (const client of clients)
148
+ client.enqueue('data: reload\n\n')
149
+ }
150
+ Bun.serve({
151
+ port: 1322,
152
+
153
+ fetch(req) {
154
+ const headers = {
155
+ 'Access-Control-Allow-Origin': '*',
156
+ 'Access-Control-Allow-Methods': 'GET',
157
+ 'Access-Control-Allow-Headers': '*',
158
+ }
159
+
160
+ if (req.method === 'OPTIONS')
161
+ return new Response(null, { status: 204, headers })
162
+
163
+ const { pathname } = new URL(req.url)
164
+
165
+ if (pathname !== '/events')
166
+ return new Response(null, { status: 404, headers })
167
+
168
+ const stream = new ReadableStream<string>({
169
+ start(controller) {
170
+ clients.add(controller)
171
+
172
+ req.signal.addEventListener('abort', () => {
173
+ clients.delete(controller)
174
+ controller.close()
175
+ })
176
+ },
177
+ })
178
+
179
+ return new Response(stream, {
180
+ headers: {
181
+ ...headers,
182
+ 'Content-Type': 'text/event-stream',
183
+ 'Cache-Control': 'no-cache',
184
+ 'Connection': 'keep-alive',
185
+ },
186
+ })
187
+ },
188
+ })
189
+
190
+ await preview({ ...config, preview: { port, host } })
191
+
192
+ log(`Running on http://${host}:${port}`)
193
+
194
+ watch(async () => {
195
+ await _build()
196
+ reload()
197
+ }, '.', _root, (path: string) => {
198
+ for (const pattern of ignore)
199
+ if (pattern.test(path)) return true
200
+
201
+ return false
202
+ })
203
+
204
+ } catch (e: any) {
205
+ error(e)
206
+ process.exit(0)
207
+ } finally {
208
+ rn()
209
+ }
210
+ })
211
+
212
+ },
213
+ })
@@ -0,0 +1,87 @@
1
+ import { command, watch, killProcess } from 't0n/cli'
2
+ import { dim } from 't0n/color'
3
+ import { error, log, rn } from 't0n/log'
4
+ import { withPort } from 't0n/port'
5
+ import { getMetadata } from '@/meta'
6
+ import { _root } from '@/utils'
7
+ import { getConfig, preview, reload } from '~/utils'
8
+
9
+ export const args = {
10
+ port: {
11
+ alias: 'p',
12
+ description: 'Port to listen on',
13
+ type: 'number',
14
+ default: 3000,
15
+ },
16
+ host: {
17
+ description: 'Host to forward requests to, defaults to the zone of project',
18
+ type: 'string',
19
+ default: 'localhost',
20
+ },
21
+ }
22
+
23
+ export default command({
24
+ meta: {
25
+ name: 'dev',
26
+ description: '🧪 Start dev server\n',
27
+ }, // @ts-ignore
28
+ args,
29
+ async run({ args }) {
30
+ 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')
33
+
34
+ let buildProcess: Bun.Subprocess | null = null
35
+
36
+ const _build = async () => {
37
+ if (buildProcess) await killProcess(buildProcess)
38
+ buildProcess = Bun.spawn(['duto', 'build', '--hmr'], {stdin: 'inherit', stdout: 'ignore', stderr: 'inherit'})
39
+
40
+ try {
41
+ const code = await buildProcess.exited
42
+
43
+ if (code !== 0)
44
+ throw new Error(`Build failed with code ${code}`)
45
+ } finally {
46
+ buildProcess = null
47
+ }
48
+ }
49
+
50
+ withPort(desiredPort, async (port) => {
51
+ const ignore = [
52
+ /(^|[\/\\])\.(duto|git|cache|vscode|idea|next|nuxt|nyc_output)([\/\\]|$)/,
53
+ /(^|[\/\\])(node_modules|tmp|dist|build|out|coverage)([\/\\]|$)/,
54
+
55
+ /\.(DS_Store|localized|tmp|temp|log|pid|swp|swo)$/,
56
+ /(Thumbs\.db|desktop\.ini)$/,
57
+ /~$/,
58
+
59
+ /(^|[\/\\])\.(Spotlight-V100|Trashes)([\/\\]|$)/,
60
+ /(^|[\/\\])__MACOSX([\/\\]|$)/,
61
+ ]
62
+
63
+ try {
64
+ await _build()
65
+ await preview(await getMetadata(config.root as string, config.pagesDir as string), host, port)
66
+
67
+ log(`Running on http://${host}:${port}${global?.__st ? dim(` in ${Math.ceil(performance.now() - global.__st)} ms`) : ''}`)
68
+
69
+ watch(async () => {
70
+ await _build()
71
+ reload()
72
+ }, '.', _root, (path: string) => {
73
+ for (const pattern of ignore)
74
+ if (pattern.test(path)) return true
75
+
76
+ return false
77
+ })
78
+ } catch (e: any) {
79
+ error(e)
80
+ process.exit(0)
81
+ } finally {
82
+ rn()
83
+ }
84
+ })
85
+
86
+ },
87
+ })
@@ -0,0 +1,33 @@
1
+ import { command } from 't0n/cli'
2
+ import { dim } from 't0n/color'
3
+ import { error, log, rn } from 't0n/log'
4
+ import { withPort } from 't0n/port'
5
+ import { getMetadata } from '@/meta'
6
+ import { _root } from '@/utils'
7
+ import { args } from './dev'
8
+ import { getConfig, preview } from '~/utils'
9
+
10
+ export default command({
11
+ meta: {
12
+ name: 'preview',
13
+ description: '💻 Locally preview production build\n',
14
+ }, // @ts-ignore
15
+ args,
16
+ async run({ args }) {
17
+ 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')
20
+
21
+ withPort(desiredPort, async (port) => {
22
+ try {
23
+ await preview(await getMetadata(config.root as string, config.pagesDir as string), host, port)
24
+ log(`Running on http://${host}:${port}${global?.__st ? dim(` in ${Math.ceil(performance.now() - global.__st)} ms`) : ''}`)
25
+ } catch (e: any) {
26
+ error('Preview failed:', e?.message || e)
27
+ process.exit(0)
28
+ } finally {
29
+ rn()
30
+ }
31
+ })
32
+ },
33
+ })
@@ -0,0 +1,36 @@
1
+ import { join, resolve } from 'node:path'
2
+ import { readFileSync } from 'node:fs'
3
+ import { resolveExtension } from './file'
4
+
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'))
12
+ const compilerOptions = tsconfig.compilerOptions || {}
13
+ const paths = Object.entries(compilerOptions.paths || {})
14
+ const baseUrl = compilerOptions.baseUrl || '.'
15
+
16
+ const aliases = {}
17
+
18
+ for (const [aliasPattern, targetPatterns] of paths) // @ts-ignore
19
+ aliases[aliasPattern.replace(/\/\*$/, '')] = resolve(process.cwd(), baseUrl, targetPatterns[0].replace(/\/\*$/, ''))
20
+
21
+ return aliases
22
+ }
23
+
24
+ export function resolveAlias(importPath: string, aliases: Record<string, string>) {
25
+ for (const [alias, realPath] of Object.entries(aliases)) {
26
+ if (importPath.startsWith(alias +'/') || importPath === alias) {
27
+ const subPath = importPath.substring(alias.length)
28
+ const cleanSubPath = subPath.startsWith('/') ? subPath.substring(1) : subPath
29
+ const resolved = join(realPath, cleanSubPath)
30
+
31
+ return resolveExtension(resolved) ?? resolved
32
+ }
33
+ }
34
+
35
+ return resolveExtension(importPath) ?? importPath
36
+ }
@@ -0,0 +1,43 @@
1
+ const distMap: Record<string, string> = {}
2
+
3
+ // export function getDist(){
4
+ // return distMap
5
+ // }
6
+ export function getAsset(id: string) {
7
+ const entry = getChunk(id, 1)
8
+ return distMap['\0'+ entry] || null
9
+ }
10
+ export function setAsset(id: string | null, val: string) {
11
+ distMap['\0'+ normalizeId(id)] = val
12
+ }
13
+
14
+ // corririr isso...
15
+ export function getChunk(id: string, deep: number = 3, loop: number = 1) {
16
+ if (!distMap[id]) return id
17
+
18
+ const currentValue = distMap[id]
19
+
20
+ if (loop < deep && distMap[currentValue] && currentValue !== id)
21
+ return getChunk(currentValue, deep, loop + 1)
22
+
23
+ return currentValue
24
+ }
25
+ export function setChunk(id: string | null, val: string) {
26
+ distMap[normalizeId(id)] = val
27
+ }
28
+
29
+ export function getEntry(id: string) {
30
+ if (id in distMap) return distMap[id]
31
+ const key = id in distMap ? id : normalizeId(id)
32
+ return distMap[key] || id
33
+ }
34
+ export function setEntry(id: string | null, val: string) {
35
+ if (!id) return
36
+ distMap[id] = normalizeId(val)
37
+ }
38
+
39
+ export function normalizeId(id?: string | null) {
40
+ id = id?.replace(process.cwd(), '') || ''
41
+ if (id && !id.startsWith('/')) id = '/'+ id
42
+ return id
43
+ }