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
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025-present, ZUNQ.com
3
+ Copyright (c) 2025-present, HUB.BI
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,26 +1,48 @@
1
- <h1 align="left">Duto<br/><a href="https://pr.new/attla/duto"><img align="right" src="https://developer.stackblitz.com/img/start_pr_dark_small.svg" alt="Start new PR in StackBlitz Codeflow"></a><a href="https://npmjs.com/package/duto"><img align="right" src="https://img.shields.io/npm/v/duto.svg" alt="npm package"></a></h1>
1
+ <h1 align="left">
2
+ 🛢 Duto &nbsp;
3
+ <a href="https://npmjs.com/package/duto"><img src="https://img.shields.io/npm/v/duto.svg" alt="npm package"></a>
4
+ <br/>
5
+ <a href="https://pr.new/attla/duto"><img align="right" src="https://developer.stackblitz.com/img/start_pr_dark_small.svg" alt="Start new PR in StackBlitz Codeflow"></a>
6
+ </h1>
2
7
 
3
8
  > ⚠️ Duto is under ALFA development — expect updates, rough edges, and occasional breack changes.
4
9
  <br/>
5
10
 
6
- This framework is fully geared towards the serverless world, specifically for static pages.
7
-
8
- - 💡 SSG
9
- - ⚡️ Dynamic static routes
10
- - 📦 Optimized Build
11
-
12
- [Read the Docs to Learn More](https://github.com/attla/duto/blob/main/DOCS.md)
11
+ Duto is minimalist framework, focused on client-side pages and serverless APIs.
12
+
13
+ Principles:
14
+ - No vendor lock-in! Deploy anywhere with: `duto deploy`
15
+ - Developer happiness as a design constraint
16
+ - Optimized by default!
17
+
18
+ Pages features:
19
+ - Static pages `/blog.tsx` `getStaticProps()`
20
+ - Prerendered dynamic pages `/blog/[slug].tsx` `getStaticProps()`
21
+ - Dynamic pages on client-side `/blog/[slug].tsx` `getProps()`
22
+ - Not found page on client-side `/blog/not-found.tsx`
23
+ - Efficient route hierarchy `/not-found.tsx`
24
+ - Catch-all page whitout SSR! `/blog/[...slug].tsx`
25
+ - Optional catch-all routes whitout SSR! `/blog/[[...slug]].tsx`
26
+ - Simple internationalization (i18n) integration `tˋfeaturesˋ`
27
+
28
+ Server features:
29
+ - Instant server and cold starts
30
+ - Optimized build, greater efficiency in less bundle size
31
+ - Built-in core shims for compatibility with custom runtimes
32
+ - Fully typed OpenAPI documentation
33
+ - Powerful request validations
34
+ - Fine-grained authentication
35
+
36
+ [Read the Docs to Learn More](https://hub.bi/docs/duto)
13
37
 
14
38
  ## Ecosystem Packages
15
39
 
16
40
  | Package | Version | Description |
17
41
  | -: | :- | :- |
18
- | [rajt](https://github.com/attla/rajt) | [![rajt version](https://img.shields.io/npm/v/rajt.svg?label=%20)](https://npm.im/rajt) | 🧱 The core of Rajt serverless framework. |
19
- | [create-rajt](https://github.com/attla/create-rajt) | [![create-rajt version](https://img.shields.io/npm/v/create-rajt.svg?label=%20)](https://npm.im/create-rajt) | 📁 CLI tool for create new Rajt projects, from starter templates. |
20
- | [forj](https://github.com/attla/forj) | [![forj version](https://img.shields.io/npm/v/forj.svg?label=%20)](https://npm.im/forj) | 🗂️ Just another query builder in typescript |
21
- | [t0n](https://github.com/attla/t0n) | [![t0n version](https://img.shields.io/npm/v/t0n.svg?label=%20)](https://npm.im/t0n) | 🧰 Collection of elegant typescript resources for web artisans. |
42
+ | [forj](https://github.com/attla/forj) | [![forj version](https://img.shields.io/npm/v/forj.svg?label=%20)](https://npm.im/forj) | 🗂️ Fast and lightweight query builder in typescript |
22
43
  | [cripta](https://github.com/attla/cripta) | [![cripta version](https://img.shields.io/npm/v/cripta.svg?label=%20)](https://npm.im/cripta) | 🧛 A layer of encryption a little too judicious. |
44
+ | [t0n](https://github.com/attla/t0n) | [![t0n version](https://img.shields.io/npm/v/t0n.svg?label=%20)](https://npm.im/t0n) | 🧰 Collection of elegant typescript resources for web artisans. |
23
45
 
24
46
  ## License
25
47
 
26
- This package is licensed under the [MIT license](https://github.com/attla/duto/blob/main/LICENSE) © [Zunq](https://zunq.com)
48
+ This package is licensed under the [MIT license](https://github.com/attla/duto/blob/main/LICENSE) © [HUB](https://hub.bi)
package/package.json CHANGED
@@ -1,50 +1,90 @@
1
1
  {
2
2
  "name": "duto",
3
- "description": "Static framework for web artisans",
4
- "version": "0.260808.0",
3
+ "description": "All-in-one serverless framework for web artisans",
4
+ "version": "0.260915.0",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
7
+ "types": "./src/index.d.ts",
8
+ "bin": "./src/cli.ts",
7
9
  "files": ["src"],
8
- "bin": "./src/cli/index.ts",
9
10
  "exports": {
10
- ".": "./src/index.ts"
11
+ ".": "./src/index.ts",
12
+ "./auth": "./src/server/auth/index.ts",
13
+ "./db": "./src/db/index.ts",
14
+ "./database": "./src/db/index.ts",
15
+ "./d1": "./src/server/db/d1.ts",
16
+ "./d1/types": "./src/server/db/d1.d.ts",
17
+ "./dynamodb": "./src/server/db/dynamodb.ts",
18
+ "./dynamodb/types": "./src/server/db/dynamodb.d.ts",
19
+ "./enum": "./src/enum.ts",
20
+ "./http": "./src/server/http.ts",
21
+ "./middleware": "./src/middleware.ts",
22
+ "./types": "./src/server/types.ts",
23
+ "./types/global": "./global.d.ts",
24
+ "./env": "./src/server/utils/environment.ts",
25
+ "./length": "./src/server/utils/length.ts"
11
26
  },
12
27
  "dependencies": {
28
+ "@inquirer/confirm": "^5.1.8",
29
+ "@inquirer/input": "^4.1.8",
30
+ "@inquirer/select": "^4.1.0",
31
+ "nanospinner": "^1.2.2",
32
+ "@hono/node-server": "^1.19.11",
33
+ "@hono/standard-validator": "^0.2.2",
34
+ "@hono/zod-validator": "^0.7.6",
35
+ "@scalar/hono-api-reference": "^0.12.0",
36
+ "@minify-html/node": "^0.18.1",
13
37
  "@preact/signals": "^2.9.2",
14
38
  "@swc/core": "^1.15.21",
15
39
  "chokidar": "^3.5.2",
16
40
  "citty": "^0.2.2",
17
41
  "consola": "^3.4.2",
18
- "filesize": "^11.0",
42
+ "cripta": "0.x",
43
+ "dotenv": "^16.5.0",
44
+ "esbuild": "^0.25.2",
45
+ "forj": "0.x",
46
+ "hono": "^4.13.7",
47
+ "hono-openapi": "^1.3.0",
48
+ "localflare-api": "^0.5.0",
49
+ "localflare-core": "^0.5.0",
50
+ "miniflare": "^4.20260730.0",
19
51
  "pathe": "^2.0",
20
52
  "preact": "^10.29.7",
21
53
  "preact-render-to-string": "^6.6.6",
54
+ "quansync": "^0.2.11",
22
55
  "t0n": "0.x",
23
56
  "vite": "^8.0.0",
24
- "wouter-preact": "^3.10.0"
57
+ "wouter-preact": "^3.10.0",
58
+ "wrangler": "^4.128.0",
59
+ "zod": "^4.3.6",
60
+ "zod-openapi": "^5.4.6"
25
61
  },
26
62
  "devDependencies": {
63
+ "@cloudflare/workers-types": "^4.20260113.0",
27
64
  "@minify-html/node": "^0.18.1",
28
65
  "@preact/preset-vite": "^2.10.5",
29
66
  "@tailwindcss/vite": "^4.3.1",
30
- "@types/node": "^25.9.0",
31
- "bun-types": "^1.3.14",
67
+ "bun-types": "^1.4.0",
32
68
  "typescript": "^5.9.3"
33
69
  },
34
- "packageManager": "bun@1.3.14",
35
- "engines": {
36
- "node": ">=18.0.0"
70
+ "resolutions": {
71
+ "@smithy/types": "^4.3.0",
72
+ "zod": "^4.3.6"
37
73
  },
74
+ "sideEffects": false,
75
+ "packageManager": "bun@1.4.0",
38
76
  "publishConfig": {
39
77
  "registry": "https://registry.npmjs.org"
40
78
  },
41
- "author": "Zunq <open-source@zunq.com>",
79
+ "author": "HUB <foss@hub.bi>",
42
80
  "license": "MIT",
43
- "homepage": "https://zunq.dev",
81
+ "homepage": "https://hub.bi/docs/duto",
44
82
  "repository": "git://github.com/attla/duto",
45
83
  "bugs": "https://github.com/attla/duto/issues",
46
84
  "keywords": [
47
85
  "SSG",
86
+ "app",
87
+ "http",
48
88
  "application",
49
89
  "framework",
50
90
  "router",
@@ -52,6 +92,7 @@
52
92
  "typescript",
53
93
  "cloudflare",
54
94
  "workers",
95
+ "workerd",
55
96
  "vercel",
56
97
  "bun"
57
98
  ]
package/src/cli.ts ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env bun
2
+
3
+ function exit(msg?: string, desc?: string) {
4
+ msg && console.error(msg)
5
+ desc && console.log(desc)
6
+ process.exit(0)
7
+ }
8
+
9
+ if (!import.meta.main)
10
+ exit('Error: Duto must be used directly as CLI command.')
11
+
12
+ if (!process?.isBun || typeof Bun === 'undefined')
13
+ exit('Error: "Bun" is not available.', ' Try install: https://bun.sh/get')
14
+
15
+ global.__st = performance.now()
16
+
17
+ import { join } from 'pathe'
18
+ import { cli } from 't0n/cli'
19
+ import { setEnv } from 't0n'
20
+ import { version } from '!/package.json'
21
+ import { _root, _duto } from './utils'
22
+
23
+ const cmd = (c: string) => join(import.meta.dirname, 'commands', c)
24
+
25
+ let pkg
26
+ let commands = {}
27
+ try {
28
+ pkg = await import(join(_root, 'package.json'))
29
+ if (!pkg || !pkg.duto || !pkg?.duto?.type || !['pages', 'server'].includes(pkg.duto.type))
30
+ exit('Error: invalid app type.')
31
+
32
+ setEnv('duto', pkg.duto)
33
+ commands = (await import(join(_duto, pkg.duto.type, 'cli')))?.default
34
+ } catch {}
35
+
36
+ cli({
37
+ name: 'duto',
38
+ description: 'Duto',
39
+ version,
40
+ commands: {
41
+ new: cmd('new'),
42
+ upgrade: cmd('upgrade'),
43
+ ...commands,
44
+ },
45
+ })
@@ -0,0 +1,147 @@
1
+ import { basename, join, relative, resolve } from 'pathe'
2
+ import { command } from 't0n/cli'
3
+ import { bold, dim, green, red } from 't0n/color'
4
+ import { event, error, step, log, rn } from 't0n/log'
5
+ import { _root } from '@/utils'
6
+
7
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
8
+ import confirm from '@inquirer/confirm'
9
+ import input from '@inquirer/input'
10
+ import select from '@inquirer/select'
11
+ import { createSpinner } from 'nanospinner'
12
+ import { exit } from 'node:process'
13
+
14
+ const templates = [
15
+ 'aws',
16
+ 'workerd',
17
+ 'vercel',
18
+ ]
19
+
20
+ const renameFiles: Record<string, string | undefined> = {
21
+ _gitignore: '.gitignore',
22
+ _gitkeep: '.gitkeep',
23
+ }
24
+
25
+
26
+ function mkdirp(dir: string) {
27
+ try {
28
+ mkdirSync(dir, { recursive: true })
29
+ } catch (e) {
30
+ if (e instanceof Error) {
31
+ if ('code' in e && e.code === 'EEXIST') {
32
+ return
33
+ }
34
+ }
35
+ throw e
36
+ }
37
+ }
38
+
39
+ function copy(src: string, dest: string) {
40
+ const stat = statSync(src)
41
+ stat.isDirectory()
42
+ ? copyDir(src, dest)
43
+ : copyFileSync(src, dest)
44
+ }
45
+ function copyDir(srcDir: string, destDir: string) {
46
+ mkdirSync(destDir, { recursive: true })
47
+ for (const file of readdirSync(srcDir)) {
48
+ const srcFile = resolve(srcDir, file)
49
+ const destFile = resolve(destDir, file)
50
+ copy(srcFile, destFile)
51
+ }
52
+ }
53
+
54
+ export default command({
55
+ meta: {
56
+ name: 'new',
57
+ description: '📄 Create new project with duto\n',
58
+ },
59
+ args: {
60
+ install: {
61
+ alias: 'i',
62
+ description: 'Install dependencies',
63
+ type: 'boolean',
64
+ default: false,
65
+ },
66
+ template: {
67
+ alias: 't',
68
+ description: 'Template to use',
69
+ type: 'enum',
70
+ options: templates,
71
+ },
72
+ },
73
+ async run({ args }) { // @ts-ignore
74
+ const root = process.cwd() || process.env?.PWD || process.stdin?.path
75
+ let dir = args._[0]
76
+ if (dir) {
77
+ step(bold('Using target directory: '+ dim('/'+ dir.replace(/^\//, ''))))
78
+ } else {
79
+ dir = await input({ message: 'Target directory', default: root })
80
+ if (!dir.startsWith(root))
81
+ dir = join(root, dir)
82
+ }
83
+
84
+ const name = basename(/^(\.\/|\.\\|\.)$/.test(dir) ? root : dir)
85
+ const template = args.template || (await select({
86
+ loop: true,
87
+ message: 'Which template do you want to use?',
88
+ choices: templates.map(v => ({ title: v, value: v})),
89
+ default: 'workerd',
90
+ }))
91
+
92
+ if (!template)
93
+ throw new Error('No template selected')
94
+
95
+ if (!templates.includes(template))
96
+ throw new Error(`Invalid template selected: ${template}`)
97
+
98
+ if (existsSync(dir) && readdirSync(dir).length > 0) {
99
+ const response = await confirm({ message: 'Directory not empty. Continue?', default: false })
100
+ if (!response) process.exit(1)
101
+ } else {
102
+ mkdirp(dir)
103
+ }
104
+
105
+ const spinner = createSpinner('Cloning the template').start()
106
+ for (const t of ['base', template]) {
107
+ const templateDir = resolve(import.meta.dir, './templates/'+ t)
108
+ const files = readdirSync(templateDir)
109
+ for (const file of files.filter(f => f !== 'package.json'))
110
+ copy(join(templateDir, file), join(dir, renameFiles[file] ?? file))
111
+ }
112
+
113
+ spinner.success()
114
+
115
+ const pkgPath = resolve(__dirname, `./templates/base/package.json`)
116
+ if (existsSync(pkgPath)) {
117
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
118
+ pkg.name = name
119
+ writeFileSync(join(dir, 'package.json'), JSON.stringify(pkg, null, 2))
120
+ }
121
+
122
+ if (args?.install) {
123
+ const spinner2 = createSpinner('Installing project dependencies').start()
124
+ const proc = Bun.spawn(['bun', 'i'], { stdout: 'ignore', stderr: 'inherit' })
125
+ const procExit = await proc.exited
126
+
127
+ if (procExit === 0) {
128
+ spinner2.success()
129
+ } else {
130
+ spinner2.stop({
131
+ mark: red('×'),
132
+ text: 'Failed to install project dependencies',
133
+ })
134
+ exit(procExit)
135
+ }
136
+ }
137
+
138
+ event('New project successfully created')
139
+ if (dir != root) {
140
+ rn()
141
+ console.log(
142
+ dim('Get started with:'),
143
+ bold(`cd ${name}`),
144
+ )
145
+ }
146
+ },
147
+ })
@@ -0,0 +1,21 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ trim_trailing_whitespace = true
8
+ indent_style = space
9
+ indent_size = 2
10
+
11
+ # [*.{js,jsx,ts,tsx,json,yaml,yml}]
12
+ # Inherits all settings from [*] and applies to these extensions
13
+
14
+ [*.{json,jsonc}]
15
+ insert_final_newline = false
16
+
17
+ [*.md]
18
+ trim_trailing_whitespace = false
19
+
20
+ [Dockerfile]
21
+ indent_size = 4
@@ -0,0 +1,2 @@
1
+ APP_NAME=duto-api
2
+ KEY=YOUR_ENCRYPT_KEY
@@ -0,0 +1,2 @@
1
+ APP_NAME=duto-api
2
+ KEY=YOUR_ENCRYPT_KEY
@@ -0,0 +1,29 @@
1
+ # Duto - Starter Template
2
+
3
+ This template should help get you started developing.
4
+
5
+ ## Install dependencies
6
+
7
+ To install, run:
8
+
9
+ ```bash
10
+ bun i
11
+ ```
12
+
13
+ ## Tests
14
+
15
+ To perform the tests, run:
16
+
17
+ ```bash
18
+ bun test
19
+ ```
20
+
21
+ ## Development environment
22
+
23
+ Test the application locally in an environment identical to production using the command:
24
+
25
+ ```bash
26
+ duto dev
27
+ ```
28
+
29
+ [Read the Full Docs to Learn More](https://hub.bi/docs/duto)
@@ -0,0 +1,100 @@
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ ## custom
4
+ .duto/
5
+ .trash
6
+ .trash*
7
+ .aws-sam
8
+ lambda.zip
9
+ packaged.yaml
10
+
11
+ # dependencies
12
+ .wrangler/
13
+ node_modules
14
+ dist/
15
+ out/
16
+ dist-ssr
17
+
18
+ # production
19
+ /build
20
+
21
+ # misc
22
+ *.pem
23
+
24
+ # debug
25
+ logs
26
+ *.log
27
+ npm-debug.log*
28
+ yarn-debug.log*
29
+ yarn-error.log*
30
+ pnpm-debug.log*
31
+ lerna-debug.log*
32
+
33
+ # local env files
34
+ .env*.local
35
+ *.local
36
+ # .env
37
+
38
+ # vercel
39
+ .vercel
40
+
41
+ # tinybird
42
+ .venv
43
+ .tinyb
44
+
45
+ # typescript
46
+ *.tsbuildinfo
47
+
48
+ # miscellaneous
49
+ /pages/api/scripts*
50
+ apps/docs/openapi.json
51
+ packages/stripe-app/.build/*
52
+ .react-email
53
+ .contentlayer
54
+ .vscode
55
+ !.vscode/extensions.json
56
+ .idea
57
+ *.suo
58
+ *.ntvs*
59
+ *.njsproj
60
+ *.sln
61
+ *.sw?
62
+ *.csv
63
+ *.ndjson
64
+ .vitest
65
+
66
+ # tests
67
+ coverage
68
+ /cypress/videos/
69
+ /cypress/screenshots/
70
+
71
+ ### macOS ###
72
+ # General
73
+ .DS_Store
74
+ .AppleDouble
75
+ .LSOverride
76
+
77
+ # Thumbnails
78
+ ._*
79
+
80
+ # Files that might appear in the root of a volume
81
+ .DocumentRevisions-V100
82
+ .fseventsd
83
+ .Spotlight-V100
84
+ .TemporaryItems
85
+ .Trashes
86
+ .VolumeIcon.icns
87
+ .com.apple.timemachine.donotpresent
88
+
89
+ # Directories potentially created on remote AFP share
90
+ .AppleDB
91
+ .AppleDesktop
92
+ Network Trash Folder
93
+ Temporary Items
94
+ .apdisk
95
+
96
+ ### macOS Patch ###
97
+ # iCloud generated files
98
+ *.icloud
99
+ # Localflare generated files
100
+ .localflare/
@@ -0,0 +1,9 @@
1
+ import type { Req, Res } from 'duto'
2
+ import { newID } from 't0n'
3
+
4
+ export async function handle(req: Req, res: Res) {
5
+ return res.ok(Array.from({ length: 5 }, () => {
6
+ const id = newID()
7
+ return { id, desc: 'Blog post #'+ id }
8
+ }))
9
+ }
@@ -0,0 +1,9 @@
1
+ import type { Req, Res } from 'duto'
2
+
3
+ export async function handle(req: Req, res: Res) {
4
+ const id = req.param('id')
5
+
6
+ return res.ok({
7
+ id, desc: 'Blog post #'+ id,
8
+ })
9
+ }
@@ -0,0 +1,5 @@
1
+ import type { Req, Res } from 'duto'
2
+
3
+ export async function handle(req: Req, res: Res) {
4
+ return res.ok({ message: 'Duto index' })
5
+ }
@@ -0,0 +1,11 @@
1
+ export default {
2
+ docs: {
3
+ path: '/docs',
4
+ agent: false,
5
+ // auth: {
6
+ // username: 'duto',
7
+ // password: 'duto',
8
+ // realm: 'Docs',
9
+ // },
10
+ }
11
+ }
@@ -0,0 +1,5 @@
1
+ export default {
2
+ admin: '*',
3
+ user: [],
4
+ guest: [],
5
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "$NAME",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "main": ".duto/index.js",
6
+ "type": "module",
7
+ "dependencies": {
8
+ "cripta": "0.x",
9
+ "t0n": "0.x"
10
+ },
11
+ "devDependencies": {
12
+ "bun-types": "catalog:",
13
+ "duto": "workspace:*",
14
+ "typescript": "catalog:",
15
+ "wrangler": "catalog:"
16
+ },
17
+ "duto": {
18
+ "type": "server",
19
+ "platform": "workerd",
20
+ "dev": {
21
+ "port": 3000
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "compilerOptions": {
3
+ "noEmit": true,
4
+ "target": "ESNext",
5
+ "module": "ESNext",
6
+ "moduleResolution": "Bundler",
7
+ "lib": ["ES2022"],
8
+ "types": ["duto"],
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "allowSyntheticDefaultImports": true,
12
+ "skipLibCheck": true,
13
+ "allowJs": true,
14
+ "resolveJsonModule": true,
15
+ "experimentalDecorators": true,
16
+ "emitDecoratorMetadata": true,
17
+ "useDefineForClassFields": false,
18
+ "rootDir": "./",
19
+ "paths": {
20
+ "@/*": [
21
+ "./*"
22
+ ]
23
+ }
24
+ },
25
+ "include": [
26
+ "actions",
27
+ "features",
28
+ "routes",
29
+ "configs",
30
+ "enums",
31
+ "libs",
32
+ "locales",
33
+ "middlewares",
34
+ "models",
35
+ "utils",
36
+ "tests/**/*"
37
+ ],
38
+ "exclude": [
39
+ ".duto",
40
+ "node_modules"
41
+ ]
42
+ }