@oyolincc/create 0.0.0-dev-20260922064135 → 0.0.0-dev-20261006065712
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/package.json +1 -1
- package/templates/hono-fullstack/.vscode/launch.json +14 -3
- package/templates/hono-fullstack/.vscode/settings.json +3 -1
- package/templates/hono-fullstack/AGENTS.md +7 -0
- package/templates/hono-fullstack/README.md +28 -14
- package/templates/hono-fullstack/_gitignore +4 -0
- package/templates/hono-fullstack/apps/server/.dev.vars.example +9 -0
- package/templates/hono-fullstack/apps/server/package.json +17 -9
- package/templates/hono-fullstack/apps/server/src/adapters/cloudflare/entry.ts +36 -0
- package/templates/hono-fullstack/apps/server/src/adapters/nodejs/bootstrap.ts +3 -6
- package/templates/hono-fullstack/apps/server/src/adapters/nodejs/entry.ts +17 -5
- package/templates/hono-fullstack/apps/server/src/app.ts +2 -2
- package/templates/hono-fullstack/apps/server/src/config.ts +47 -0
- package/templates/hono-fullstack/apps/server/src/infra/logger/pino.ts +4 -0
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/example/worker-entry.ts +4 -25
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/pass-through/runner.ts +42 -0
- package/templates/{hono-server/apps/server/src/infra/work-runner/example → hono-fullstack/apps/server/src/infra/work-runner/piscina}/runner.ts +9 -9
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/types.ts +7 -2
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/utils/message.ts +7 -4
- package/templates/hono-fullstack/apps/server/src/modules/example/routes.ts +3 -5
- package/templates/hono-fullstack/apps/server/src/modules/example/work-task/tasks.test.ts +17 -5
- package/templates/hono-fullstack/apps/server/src/modules/example/work-task/tasks.ts +38 -15
- package/templates/hono-fullstack/apps/server/src/shared/app/types.ts +3 -4
- package/templates/hono-fullstack/apps/server/tsconfig.json +1 -0
- package/templates/hono-fullstack/apps/server/vite.config.ts +8 -3
- package/templates/hono-fullstack/apps/server/wrangler.jsonc +29 -0
- package/templates/hono-fullstack/apps/stack/backend/cloudflare.ts +5 -0
- package/templates/hono-fullstack/apps/stack/backend/node.ts +3 -0
- package/templates/hono-fullstack/apps/stack/frontend/components/general/ErrorMessage.tsx +4 -0
- package/templates/hono-fullstack/apps/stack/frontend/components/layouts/AppLayout.tsx +11 -0
- package/templates/hono-fullstack/apps/stack/frontend/components/layouts/Header.tsx +7 -0
- package/templates/hono-fullstack/apps/stack/frontend/components/layouts/Page.tsx +5 -0
- package/templates/hono-fullstack/apps/stack/frontend/components/layouts/PageContainer.tsx +5 -0
- package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExampleForm.tsx +45 -0
- package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExampleList.tsx +13 -0
- package/templates/hono-fullstack/apps/stack/frontend/routeTree.gen.ts +21 -4
- package/templates/hono-fullstack/apps/stack/frontend/routes/api/$.ts +18 -0
- package/templates/hono-fullstack/apps/stack/frontend/routes/index.tsx +48 -2
- package/templates/hono-fullstack/apps/stack/frontend/vite-env.d.ts +5 -0
- package/templates/hono-fullstack/apps/stack/package.json +20 -5
- package/templates/hono-fullstack/apps/stack/tsconfig.json +2 -1
- package/templates/hono-fullstack/apps/stack/vite.config.ts +75 -26
- package/templates/hono-fullstack/apps/stack/wrangler.jsonc +20 -0
- package/templates/hono-fullstack/envs/.env.example.server +1 -1
- package/templates/hono-fullstack/envs/.env.example.sqlite-d1 +3 -0
- package/templates/hono-fullstack/libs/db/drizzle-kit/sqlite-d1.config.ts +22 -0
- package/templates/hono-fullstack/libs/db/package.json +8 -6
- package/templates/hono-fullstack/libs/db/src/dialects/sqlite/d1-client.ts +12 -0
- package/templates/hono-fullstack/libs/db/src/dialects/sqlite/schema/columns.ts +5 -0
- package/templates/hono-fullstack/libs/db/src/dialects/sqlite/schema/modules/examples/examples.ts +2 -2
- package/templates/hono-fullstack/libs/db/vite.config.ts +1 -0
- package/templates/hono-fullstack/libs/definition/src/configs/defs/runtime.ts +1 -0
- package/templates/hono-fullstack/libs/definition/src/configs/defs/sqlite.ts +16 -3
- package/templates/hono-fullstack/oyo.config.json +2 -1
- package/templates/hono-fullstack/package.json +1 -1
- package/templates/hono-fullstack/pnpm-workspace.yaml +7 -5
- package/templates/hono-fullstack/turbo.json +25 -3
- package/templates/hono-fullstack/vite.config.ts +1 -0
- package/templates/hono-server/.vscode/launch.json +7 -3
- package/templates/hono-server/.vscode/settings.json +3 -1
- package/templates/hono-server/AGENTS.md +7 -0
- package/templates/hono-server/README.md +25 -12
- package/templates/hono-server/_gitignore +4 -0
- package/templates/hono-server/apps/server/.dev.vars.example +9 -0
- package/templates/hono-server/apps/server/package.json +18 -8
- package/templates/hono-server/apps/server/src/adapters/cloudflare/entry.ts +36 -0
- package/templates/hono-server/apps/server/src/adapters/nodejs/bootstrap.ts +3 -3
- package/templates/hono-server/apps/server/src/adapters/nodejs/entry.ts +24 -4
- package/templates/hono-server/apps/server/src/app.ts +2 -2
- package/templates/hono-server/apps/server/src/config.ts +47 -0
- package/templates/hono-server/apps/server/src/infra/logger/pino.ts +4 -0
- package/templates/hono-server/apps/server/src/infra/work-runner/example/worker-entry.ts +4 -25
- package/templates/hono-server/apps/server/src/infra/work-runner/pass-through/runner.ts +42 -0
- package/templates/{hono-fullstack/apps/server/src/infra/work-runner/example → hono-server/apps/server/src/infra/work-runner/piscina}/runner.ts +9 -9
- package/templates/hono-server/apps/server/src/infra/work-runner/types.ts +7 -2
- package/templates/hono-server/apps/server/src/infra/work-runner/utils/message.ts +7 -4
- package/templates/hono-server/apps/server/src/modules/example/contracts.ts +4 -0
- package/templates/hono-server/apps/server/src/modules/example/routes.ts +32 -5
- package/templates/hono-server/apps/server/src/modules/example/work-task/tasks.test.ts +17 -5
- package/templates/hono-server/apps/server/src/modules/example/work-task/tasks.ts +38 -15
- package/templates/hono-server/apps/server/src/shared/app/types.ts +3 -4
- package/templates/hono-server/apps/server/tsconfig.json +1 -0
- package/templates/hono-server/apps/server/vite.config.ts +8 -3
- package/templates/hono-server/apps/server/wrangler.jsonc +29 -0
- package/templates/hono-server/docker/server.Dockerfile +3 -5
- package/templates/hono-server/envs/.env.example.server +1 -1
- package/templates/hono-server/envs/.env.example.sqlite +1 -0
- package/templates/hono-server/envs/.env.example.sqlite-d1 +3 -0
- package/templates/hono-server/libs/db/drizzle-kit/sqlite-d1.config.ts +22 -0
- package/templates/hono-server/libs/db/drizzle-kit/sqlite.config.ts +22 -0
- package/templates/hono-server/libs/db/package.json +42 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/client.ts +35 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/d1-client.ts +12 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/columns.ts +37 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/index.ts +7 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/modules/examples/examples.ts +22 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/relations.ts +5 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/tables.ts +5 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/types.ts +7 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/vo.ts +1 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/utils.ts +8 -0
- package/templates/hono-server/libs/db/src/shared/types.ts +26 -0
- package/templates/hono-server/libs/db/tsconfig.json +10 -0
- package/templates/hono-server/libs/db/vite.config.ts +22 -0
- package/templates/hono-server/libs/definition/src/configs/defs/runtime.ts +1 -0
- package/templates/hono-server/libs/definition/src/configs/defs/sqlite.ts +26 -0
- package/templates/hono-server/libs/definition/src/configs/index.ts +1 -0
- package/templates/hono-server/oyo.config.json +3 -1
- package/templates/hono-server/package.json +2 -3
- package/templates/hono-server/pnpm-workspace.yaml +12 -3
- package/templates/hono-server/turbo.json +25 -3
- package/templates/hono-server/vite.config.ts +1 -0
- package/templates/monorepo/.vscode/launch.json +0 -3
- package/templates/monorepo/.vscode/settings.json +3 -1
- package/templates/monorepo/AGENTS.md +7 -0
- package/templates/monorepo/_gitignore +4 -0
- package/templates/monorepo/pnpm-workspace.yaml +6 -3
- package/templates/monorepo/turbo.json +25 -3
- package/templates/monorepo/vite.config.ts +1 -0
- package/templates/hono-fullstack/apps/server/src/adapters/nodejs/config.ts +0 -53
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/example/runner.test.ts +0 -56
- package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExamplePage.tsx +0 -59
- package/templates/hono-fullstack/apps/stack/nitro/handlers/hono.ts +0 -1
- package/templates/hono-fullstack/apps/stack/nitro/plugins/hono.ts +0 -9
- package/templates/hono-server/apps/server/src/adapters/nodejs/config.ts +0 -53
- package/templates/hono-server/apps/server/src/infra/work-runner/example/runner.test.ts +0 -56
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
],
|
|
8
8
|
"type": "module",
|
|
9
9
|
"exports": {
|
|
10
|
+
"./sqlite/d1-client": "./dist/sqlite/d1-client.mjs",
|
|
10
11
|
"./sqlite/schema": "./dist/sqlite/schema.mjs",
|
|
11
12
|
"./sqlite/sqlite": "./dist/sqlite/sqlite.mjs",
|
|
12
13
|
"./package.json": "./package.json"
|
|
@@ -19,20 +20,21 @@
|
|
|
19
20
|
"sqlite:export": "oyo env sqlite -- drizzle-kit export --config=drizzle-kit/sqlite.config.ts",
|
|
20
21
|
"dev:sqlite:push": "oyo env sqlite -- drizzle-kit push --config=drizzle-kit/sqlite.config.ts",
|
|
21
22
|
"dev:sqlite:gen": "oyo env sqlite -- drizzle-kit generate --config=drizzle-kit/sqlite.config.ts",
|
|
22
|
-
"dev:sqlite:migrate": "oyo env sqlite -- drizzle-kit migrate --config=drizzle-kit/sqlite.config.ts"
|
|
23
|
+
"dev:sqlite:migrate": "oyo env sqlite -- drizzle-kit migrate --config=drizzle-kit/sqlite.config.ts",
|
|
24
|
+
"dev:d1:gen": "oyo env sqlite-d1 -- drizzle-kit generate --config=drizzle-kit/sqlite-d1.config.ts",
|
|
25
|
+
"dev:d1:migrate": "oyo env sqlite-d1 -- drizzle-kit migrate --config=drizzle-kit/sqlite-d1.config.ts"
|
|
23
26
|
},
|
|
24
27
|
"dependencies": {
|
|
25
28
|
"@repo/definition": "workspace:*",
|
|
26
|
-
"better-sqlite3": "catalog:
|
|
27
|
-
"drizzle-orm": "catalog:
|
|
29
|
+
"better-sqlite3": "catalog:db",
|
|
30
|
+
"drizzle-orm": "catalog:db"
|
|
28
31
|
},
|
|
29
32
|
"devDependencies": {
|
|
30
|
-
"@cloudflare/workers-types": "catalog:drizzle",
|
|
31
33
|
"@oyolincc/cli": "catalog:",
|
|
32
34
|
"@oyolincc/dev-config": "catalog:",
|
|
33
|
-
"@types/better-sqlite3": "catalog:
|
|
35
|
+
"@types/better-sqlite3": "catalog:db",
|
|
34
36
|
"@types/node": "catalog:",
|
|
35
|
-
"drizzle-kit": "catalog:
|
|
37
|
+
"drizzle-kit": "catalog:db",
|
|
36
38
|
"tsx": "catalog:",
|
|
37
39
|
"typescript": "catalog:",
|
|
38
40
|
"vite-plus": "catalog:"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { drizzle, type AnyD1Database } from 'drizzle-orm/d1'
|
|
2
|
+
import { relations } from './schema'
|
|
3
|
+
|
|
4
|
+
export type D1Binding = AnyD1Database
|
|
5
|
+
|
|
6
|
+
export function createD1Client(database: D1Binding) {
|
|
7
|
+
if (!database) throw new Error('database must not be empty')
|
|
8
|
+
|
|
9
|
+
const db = drizzle(database, { relations })
|
|
10
|
+
|
|
11
|
+
return { db }
|
|
12
|
+
}
|
|
@@ -10,6 +10,11 @@ export const idType = customType<{ data: string; driverData: number | bigint }>(
|
|
|
10
10
|
},
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
+
export const autoIncrementId = (name: string) =>
|
|
14
|
+
idType(name)
|
|
15
|
+
.primaryKey({ autoIncrement: true })
|
|
16
|
+
.$defaultFn(() => sql`null`)
|
|
17
|
+
|
|
13
18
|
export function timestampMsColumn(name: string) {
|
|
14
19
|
return integer(name, { mode: 'timestamp_ms' })
|
|
15
20
|
.notNull()
|
package/templates/hono-fullstack/libs/db/src/dialects/sqlite/schema/modules/examples/examples.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { sqliteTable, text } from 'drizzle-orm/sqlite-core'
|
|
2
|
-
import {
|
|
2
|
+
import { autoIncrementId, modifiedTimeCols } from '../../columns'
|
|
3
3
|
import type { SelectVOResults } from '@/shared/types'
|
|
4
4
|
import { defineVO } from '@/shared/types'
|
|
5
5
|
|
|
6
6
|
export const examples = sqliteTable('examples', {
|
|
7
|
-
id:
|
|
7
|
+
id: autoIncrementId('id'),
|
|
8
8
|
message: text('message').notNull(),
|
|
9
9
|
...modifiedTimeCols(),
|
|
10
10
|
})
|
|
@@ -2,6 +2,7 @@ import * as v from 'valibot'
|
|
|
2
2
|
import { defineSchemaConfig } from '../proto'
|
|
3
3
|
|
|
4
4
|
export const $S_RuntimeConfig = v.object({
|
|
5
|
+
serverBasePath: v.optional(v.string(), '/'),
|
|
5
6
|
serverEnv: v.optional(
|
|
6
7
|
v.union([v.literal('local'), v.literal('test'), v.literal('staging'), v.literal('main')]),
|
|
7
8
|
'local',
|
|
@@ -3,11 +3,24 @@ import * as v from 'valibot'
|
|
|
3
3
|
import { defineSchemaConfig } from '../proto'
|
|
4
4
|
import { $S_NonEmptyString } from '../schema'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const
|
|
6
|
+
function defaultSqliteDbPath(): string {
|
|
7
|
+
const workspaceRoot = path.join(import.meta.dirname, '../../..')
|
|
8
|
+
return path.join(workspaceRoot, 'db-data', 'repo.sqlite')
|
|
9
|
+
}
|
|
8
10
|
|
|
9
11
|
export const $S_SqliteSchemaConfig = v.object({
|
|
10
|
-
dbPath: v.
|
|
12
|
+
dbPath: v.pipe(
|
|
13
|
+
v.optional($S_NonEmptyString),
|
|
14
|
+
v.transform((dbPath) => dbPath || defaultSqliteDbPath()),
|
|
15
|
+
) as v.GenericSchema<string | undefined, string>,
|
|
11
16
|
})
|
|
12
17
|
export type SqliteSchemaConfig = v.InferOutput<typeof $S_SqliteSchemaConfig>
|
|
13
18
|
export const sqliteSchemaConfig = defineSchemaConfig($S_SqliteSchemaConfig)
|
|
19
|
+
|
|
20
|
+
export const $S_D1SchemaConfig = v.object({
|
|
21
|
+
cloudflareAccountId: $S_NonEmptyString,
|
|
22
|
+
cloudflareDatabaseId: $S_NonEmptyString,
|
|
23
|
+
cloudflareToken: $S_NonEmptyString,
|
|
24
|
+
})
|
|
25
|
+
export type D1SchemaConfig = v.InferOutput<typeof $S_D1SchemaConfig>
|
|
26
|
+
export const d1SchemaConfig = defineSchemaConfig($S_D1SchemaConfig)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"prepare": "vp config",
|
|
7
7
|
"changeset": "vp exec changeset",
|
|
8
8
|
"build": "turbo build",
|
|
9
|
-
"build:libs": "turbo build --filter=!@repo/stack"
|
|
9
|
+
"build:libs": "turbo build --filter=!@repo/stack --filter=!@repo/server"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@changesets/changelog-github": "catalog:",
|
|
@@ -8,6 +8,7 @@ catalogPrune: true
|
|
|
8
8
|
catalog:
|
|
9
9
|
'@changesets/changelog-github': '0.5.0'
|
|
10
10
|
'@changesets/cli': '2.27.12'
|
|
11
|
+
'@cloudflare/vite-plugin': '1.62.5'
|
|
11
12
|
'@oyolincc/cli': '2.1.3'
|
|
12
13
|
'@oyolincc/dev-config': '0.1.1'
|
|
13
14
|
'@oyolincc/env-loader': '^0.2.0'
|
|
@@ -21,8 +22,9 @@ catalog:
|
|
|
21
22
|
'tsx': '4.21.0'
|
|
22
23
|
'turbo': '^2.9.14'
|
|
23
24
|
'typescript': '7.0.2'
|
|
24
|
-
'vite': 'npm:@voidzero-dev/vite-plus-core@0.
|
|
25
|
-
'vite-plus': '0.
|
|
25
|
+
'vite': 'npm:@voidzero-dev/vite-plus-core@0.3.1'
|
|
26
|
+
'vite-plus': '0.3.1'
|
|
27
|
+
'wrangler': '4.147.0'
|
|
26
28
|
|
|
27
29
|
catalogs:
|
|
28
30
|
shared:
|
|
@@ -61,15 +63,14 @@ catalogs:
|
|
|
61
63
|
'react': '19.2.7'
|
|
62
64
|
'react-dom': '19.2.7'
|
|
63
65
|
'tailwindcss': '^4.3.3'
|
|
64
|
-
|
|
65
|
-
'@cloudflare/workers-types': '5.20260823.1'
|
|
66
|
+
db:
|
|
66
67
|
'@types/better-sqlite3': '^7.6.13'
|
|
67
68
|
'better-sqlite3': '^12.11.1'
|
|
68
69
|
'drizzle-kit': '1.0.0-rc.4'
|
|
69
70
|
'drizzle-orm': '1.0.0-rc.4'
|
|
70
71
|
|
|
71
72
|
overrides:
|
|
72
|
-
'vite': 'catalog:'
|
|
73
|
+
'vite@*': 'catalog:'
|
|
73
74
|
|
|
74
75
|
peerDependencyRules:
|
|
75
76
|
allowAny:
|
|
@@ -80,3 +81,4 @@ peerDependencyRules:
|
|
|
80
81
|
allowBuilds:
|
|
81
82
|
'better-sqlite3': true
|
|
82
83
|
'esbuild': true
|
|
84
|
+
'workerd': true
|
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://turbo.build/schema.json",
|
|
3
3
|
"tasks": {
|
|
4
|
-
"
|
|
4
|
+
"dev": {
|
|
5
5
|
"dependsOn": ["^build"],
|
|
6
|
-
"
|
|
6
|
+
"cache": false,
|
|
7
|
+
"persistent": true
|
|
7
8
|
},
|
|
8
|
-
"dev": {
|
|
9
|
+
"dev:node": {
|
|
10
|
+
"dependsOn": ["^build"],
|
|
11
|
+
"env": ["DEPLOY_TARGET"],
|
|
12
|
+
"cache": false,
|
|
13
|
+
"persistent": true
|
|
14
|
+
},
|
|
15
|
+
"dev:cloudflare": {
|
|
9
16
|
"dependsOn": ["^build"],
|
|
17
|
+
"env": ["DEPLOY_TARGET"],
|
|
10
18
|
"cache": false,
|
|
11
19
|
"persistent": true
|
|
20
|
+
},
|
|
21
|
+
"build": {
|
|
22
|
+
"dependsOn": ["^build"],
|
|
23
|
+
"outputs": ["dist/**", ".output/**"]
|
|
24
|
+
},
|
|
25
|
+
"build:node": {
|
|
26
|
+
"dependsOn": ["^build"],
|
|
27
|
+
"env": ["DEPLOY_TARGET"],
|
|
28
|
+
"outputs": ["dist/**", ".output/**"]
|
|
29
|
+
},
|
|
30
|
+
"build:cloudflare": {
|
|
31
|
+
"dependsOn": ["^build"],
|
|
32
|
+
"env": ["DEPLOY_TARGET"],
|
|
33
|
+
"outputs": ["dist/**", ".output/**"]
|
|
12
34
|
}
|
|
13
35
|
}
|
|
14
36
|
}
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
"sourceMaps": true,
|
|
11
11
|
"type": "node-terminal"
|
|
12
12
|
},
|
|
13
|
+
{
|
|
14
|
+
"command": "pnpm -C apps/server dev:node-chain",
|
|
15
|
+
"name": "repo-server",
|
|
16
|
+
"request": "launch",
|
|
17
|
+
"sourceMaps": true,
|
|
18
|
+
"type": "node-terminal"
|
|
19
|
+
},
|
|
13
20
|
{
|
|
14
21
|
"name": "Attach to process",
|
|
15
22
|
"port": 19230,
|
|
@@ -18,8 +25,5 @@
|
|
|
18
25
|
"type": "node"
|
|
19
26
|
}
|
|
20
27
|
],
|
|
21
|
-
// Use IntelliSense to learn about possible attributes.
|
|
22
|
-
// Hover to view descriptions of existing attributes.
|
|
23
|
-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
24
28
|
"version": "0.2.0"
|
|
25
29
|
}
|
|
@@ -10,6 +10,13 @@ Docs are local at `node_modules/vite-plus/docs` or online at https://viteplus.de
|
|
|
10
10
|
|
|
11
11
|
`vp <name>` runs a built-in command. `vp run <name>` runs a `package.json` script or a `vite.config.ts` task. Scripts cannot overwrite built-ins, so `vp dev` and `vp run dev` may do different things. Check `package.json` and `vite.config.ts` first, and run `vp run <name>` when the project defines a script or task with that name.
|
|
12
12
|
|
|
13
|
+
## Tool Versions
|
|
14
|
+
|
|
15
|
+
Run `vp toolchain` to show versions and relationships in the active Vite+
|
|
16
|
+
release. Add a tool name to select part of the graph. For example, run
|
|
17
|
+
`vp toolchain vite`. Use `--global` to ignore the local `vite-plus` package. Use
|
|
18
|
+
`vp why <package>` to show the package-manager dependency graph.
|
|
19
|
+
|
|
13
20
|
## Review Checklist
|
|
14
21
|
|
|
15
22
|
- [ ] Run `vp install` after pulling remote changes and before getting started.
|
|
@@ -1,31 +1,44 @@
|
|
|
1
1
|
# Hono server monorepo
|
|
2
2
|
|
|
3
|
-
This template contains
|
|
3
|
+
This template contains Node.js and Cloudflare Hono adapters, SQLite/D1 persistence, shared definitions, the complete optional Piscina worker infrastructure, and standalone Docker deployment files.
|
|
4
4
|
|
|
5
5
|
## Layout
|
|
6
6
|
|
|
7
|
-
- `apps/server`:
|
|
7
|
+
- `apps/server`: Hono application, Node.js and Cloudflare adapters, logging, errors, and worker runtime.
|
|
8
8
|
- `libs/definition`: backend contracts and environment definitions.
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
9
|
+
- `libs/db`: SQLite/Drizzle and D1 clients, schema, relations, and manual migration commands.
|
|
10
|
+
- `envs`: committed environment examples.
|
|
11
|
+
- `docker` and `scripts`: local and production standalone Node container workflows.
|
|
11
12
|
|
|
12
13
|
## Setup
|
|
13
14
|
|
|
14
15
|
```bash
|
|
15
16
|
pnpm install
|
|
17
|
+
pnpm --filter @repo/server cf:typegen
|
|
18
|
+
cp apps/server/.dev.vars.example apps/server/.dev.vars
|
|
16
19
|
cp envs/.env.example.server envs/.env.server
|
|
20
|
+
cp envs/.env.example.sqlite envs/.env.sqlite
|
|
21
|
+
cp envs/.env.example.sqlite-d1 envs/.env.sqlite-d1
|
|
17
22
|
pnpm prepare
|
|
18
|
-
pnpm dev
|
|
23
|
+
pnpm --filter @repo/db dev:sqlite:push
|
|
24
|
+
pnpm -C apps/server dev:node-chain
|
|
19
25
|
```
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
Database schema changes remain manual. Production Worker variables are configured in the Cloudflare dashboard; `.dev.vars` is only for local development.
|
|
28
|
+
|
|
29
|
+
Before deploying, replace the placeholder D1 `database_id` and `database_name` in `apps/server/wrangler.jsonc`.
|
|
30
|
+
|
|
31
|
+
Example tasks run in-process through `PassThroughWorkRunner` by default. To use worker threads, enable `PiscinaWorkRunner` in the Node.js adapter and the adjacent worker pack entry in `apps/server/vite.config.ts`.
|
|
22
32
|
|
|
23
33
|
## Commands
|
|
24
34
|
|
|
25
|
-
- `pnpm dev`:
|
|
26
|
-
- `pnpm
|
|
27
|
-
- `pnpm
|
|
28
|
-
- `pnpm --filter @repo/
|
|
29
|
-
- `pnpm --filter @repo/
|
|
35
|
+
- `pnpm -C apps/server dev:node-chain`: build upstream dependencies, then watch the Node.js server and its dependencies.
|
|
36
|
+
- `pnpm -C apps/server dev:cloudflare-chain`: build upstream dependencies, then watch the Cloudflare server and its dependencies.
|
|
37
|
+
- `pnpm build`: build all workspace packages.
|
|
38
|
+
- `pnpm --filter @repo/db dev:sqlite:push`: push the local SQLite schema manually.
|
|
39
|
+
- `pnpm --filter @repo/db dev:d1:gen` / `pnpm --filter @repo/db dev:d1:migrate`: generate or apply D1 migrations manually.
|
|
40
|
+
- `pnpm --filter @repo/server cf:typegen`: generate Cloudflare runtime and binding types.
|
|
41
|
+
- `pnpm --filter @repo/server docker:build`: build the standalone Node.js image.
|
|
42
|
+
- `pnpm --filter @repo/server test`: run the retained server tests.
|
|
30
43
|
|
|
31
|
-
Docker supports local Compose under `docker/local` and production Compose under `docker/prod`.
|
|
44
|
+
The server base path is configured by `SERVER_BASE_PATH`. Health, OpenAPI YAML, Swagger, CRUD, and worker processing are available below that base path. Docker supports local Compose under `docker/local` and production Compose under `docker/prod`. CI is intentionally not included.
|
|
@@ -2,18 +2,25 @@
|
|
|
2
2
|
"name": "@repo/server",
|
|
3
3
|
"version": "0.0.0",
|
|
4
4
|
"private": true,
|
|
5
|
-
"files": [
|
|
6
|
-
"dist"
|
|
7
|
-
],
|
|
5
|
+
"files": ["dist"],
|
|
8
6
|
"type": "module",
|
|
9
7
|
"exports": {
|
|
10
|
-
"./
|
|
8
|
+
"./nodejs": "./dist/nodejsEntry.mjs",
|
|
9
|
+
"./cloudflare": "./dist/cloudflareEntry.mjs",
|
|
11
10
|
"./package.json": "./package.json"
|
|
12
11
|
},
|
|
13
12
|
"scripts": {
|
|
14
|
-
"dev": "
|
|
15
|
-
"
|
|
16
|
-
"
|
|
13
|
+
"dev": "pnpm dev:node",
|
|
14
|
+
"build": "pnpm build:node",
|
|
15
|
+
"dev:node-chain": "turbo watch dev:node --filter=@repo/server",
|
|
16
|
+
"dev:node": "concurrently -k -n dev,pack -c blue,green \"vp dev\" \"VITE_PUBLIC_DEV_SERVE=1 vp pack --watch\"",
|
|
17
|
+
"dev:cloudflare-chain": "turbo watch dev:cloudflare --filter=@repo/server",
|
|
18
|
+
"dev:cloudflare": "wrangler dev --config wrangler.jsonc --persist-to ../../.wrangler/state",
|
|
19
|
+
"db:migrate:cloudflare:local": "wrangler d1 migrations apply DB --local --config wrangler.jsonc --persist-to ../../.wrangler/state",
|
|
20
|
+
"build:node-chain": "turbo build:node --filter=@repo/server",
|
|
21
|
+
"build:node": "vp pack",
|
|
22
|
+
"cf:typegen": "wrangler types --config wrangler.jsonc",
|
|
23
|
+
"cf:typecheck": "wrangler types --config wrangler.jsonc --check",
|
|
17
24
|
"test": "vp test",
|
|
18
25
|
"check": "vp check",
|
|
19
26
|
"docker:build": "bash ../../scripts/build-docker-server.sh"
|
|
@@ -22,11 +29,13 @@
|
|
|
22
29
|
"@hono/node-server": "catalog:server",
|
|
23
30
|
"@hono/standard-validator": "catalog:server",
|
|
24
31
|
"@hono/swagger-ui": "catalog:server",
|
|
32
|
+
"@repo/db": "workspace:*",
|
|
25
33
|
"@repo/definition": "workspace:*",
|
|
26
34
|
"@valibot/to-json-schema": "catalog:server",
|
|
27
35
|
"change-case": "catalog:shared",
|
|
28
36
|
"defu": "catalog:shared",
|
|
29
37
|
"dotenv": "catalog:",
|
|
38
|
+
"drizzle-orm": "catalog:db",
|
|
30
39
|
"hono": "catalog:server",
|
|
31
40
|
"hono-openapi": "catalog:server",
|
|
32
41
|
"hono-pino": "catalog:server",
|
|
@@ -49,6 +58,7 @@
|
|
|
49
58
|
"pino-pretty": "catalog:server",
|
|
50
59
|
"tsx": "catalog:",
|
|
51
60
|
"typescript": "catalog:",
|
|
52
|
-
"vite-plus": "catalog:"
|
|
61
|
+
"vite-plus": "catalog:",
|
|
62
|
+
"wrangler": "catalog:"
|
|
53
63
|
}
|
|
54
64
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createD1Client } from '@repo/db/sqlite/d1-client'
|
|
2
|
+
import { env } from 'cloudflare:workers'
|
|
3
|
+
import { getRuntimeKey } from 'hono/adapter'
|
|
4
|
+
import { createApp } from '@/app'
|
|
5
|
+
import { resolveConfig } from '@/config'
|
|
6
|
+
import { setRootLogger } from '@/infra/logger/getter'
|
|
7
|
+
import { createPinoLogger } from '@/infra/logger/pino'
|
|
8
|
+
import { PassThroughWorkRunner } from '@/infra/work-runner/pass-through/runner'
|
|
9
|
+
import type { AppDependencies, AppLogger } from '@/shared/app/types'
|
|
10
|
+
|
|
11
|
+
const appConfig = resolveConfig(env as any)
|
|
12
|
+
const { runtime, log } = appConfig
|
|
13
|
+
const { rootLogger, loggerHandler } = createPinoLogger({
|
|
14
|
+
isLocal: runtime.isLocal,
|
|
15
|
+
logBase: log.base,
|
|
16
|
+
runtime: getRuntimeKey(),
|
|
17
|
+
logRoll: log.roll,
|
|
18
|
+
logPretty: log.pretty,
|
|
19
|
+
})
|
|
20
|
+
setRootLogger(rootLogger as unknown as AppLogger)
|
|
21
|
+
|
|
22
|
+
export const workRunner = new PassThroughWorkRunner()
|
|
23
|
+
const d1Client = createD1Client(env.DB)
|
|
24
|
+
const dependencies: AppDependencies = {
|
|
25
|
+
appConfig,
|
|
26
|
+
loggerHandler,
|
|
27
|
+
workRunner,
|
|
28
|
+
db: d1Client.db,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const app = createApp({
|
|
32
|
+
serverBasePath: appConfig.runtime.serverBasePath,
|
|
33
|
+
makeDependencies: () => dependencies,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
export default app
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { serve } from '@hono/node-server'
|
|
2
|
-
import app, {
|
|
2
|
+
import app, { closeNodeDependencies } from './entry'
|
|
3
3
|
|
|
4
4
|
function main() {
|
|
5
5
|
const port = Number(process.env.NODE_PORT)
|
|
@@ -38,8 +38,8 @@ function main() {
|
|
|
38
38
|
})
|
|
39
39
|
console.log('✔ HTTP server successfully closed.')
|
|
40
40
|
|
|
41
|
-
await
|
|
42
|
-
console.log('✔
|
|
41
|
+
await closeNodeDependencies()
|
|
42
|
+
console.log('✔ Node dependencies successfully closed.')
|
|
43
43
|
|
|
44
44
|
console.log('Graceful shutdown completed.')
|
|
45
45
|
process.exit(0)
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { createSqliteClient } from '@repo/db/sqlite/sqlite'
|
|
2
|
+
import { sqliteSchemaConfig } from '@repo/definition/backend'
|
|
1
3
|
import { createApp } from '@/app'
|
|
2
|
-
import { resolveConfig } from '
|
|
4
|
+
import { resolveConfig } from '@/config'
|
|
3
5
|
import { createPinoLogger } from '@/infra/logger/pino'
|
|
4
6
|
import { getRuntimeKey } from 'hono/adapter'
|
|
5
7
|
import type { AppDependencies, AppLogger } from '@/shared/app/types'
|
|
6
|
-
import {
|
|
8
|
+
// import { PiscinaWorkRunner } from '@/infra/work-runner/piscina/runner'
|
|
9
|
+
import { PassThroughWorkRunner } from '@/infra/work-runner/pass-through/runner'
|
|
7
10
|
import { getLogger, setRootLogger } from '@/infra/logger/getter'
|
|
8
11
|
|
|
9
12
|
function installProcessErrorHandlers(isLocal: boolean) {
|
|
@@ -18,6 +21,10 @@ function installProcessErrorHandlers(isLocal: boolean) {
|
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
const appConfig = resolveConfig(process.env)
|
|
24
|
+
const sqliteConfig = sqliteSchemaConfig.resolve({
|
|
25
|
+
context: process.env,
|
|
26
|
+
matchContextKey: 'constantCase',
|
|
27
|
+
})
|
|
21
28
|
const { runtime, log } = appConfig
|
|
22
29
|
const { rootLogger, loggerHandler } = createPinoLogger({
|
|
23
30
|
isLocal: runtime.isLocal,
|
|
@@ -29,14 +36,27 @@ const { rootLogger, loggerHandler } = createPinoLogger({
|
|
|
29
36
|
setRootLogger(rootLogger as unknown as AppLogger)
|
|
30
37
|
installProcessErrorHandlers(runtime.isLocal)
|
|
31
38
|
|
|
32
|
-
|
|
39
|
+
// To enable Piscina, use PiscinaWorkRunner and enable the worker pack entry in vite.config.ts.
|
|
40
|
+
// export const workRunner = PiscinaWorkRunner.getInstance(appConfig.worker)
|
|
41
|
+
export const workRunner = new PassThroughWorkRunner()
|
|
42
|
+
export const sqliteClient = createSqliteClient(sqliteConfig.dbPath)
|
|
33
43
|
|
|
34
44
|
let dependencies: AppDependencies | undefined
|
|
45
|
+
let closePromise: Promise<void> | undefined
|
|
35
46
|
const app = createApp({
|
|
47
|
+
serverBasePath: appConfig.runtime.serverBasePath,
|
|
36
48
|
makeDependencies: () => {
|
|
37
|
-
dependencies ||= { appConfig, loggerHandler,
|
|
49
|
+
dependencies ||= { appConfig, loggerHandler, workRunner, db: sqliteClient.db }
|
|
38
50
|
return dependencies
|
|
39
51
|
},
|
|
40
52
|
})
|
|
41
53
|
|
|
54
|
+
export const closeNodeDependencies = (): Promise<void> => {
|
|
55
|
+
closePromise ||= (async () => {
|
|
56
|
+
await workRunner.shutdown()
|
|
57
|
+
sqliteClient.close()
|
|
58
|
+
})()
|
|
59
|
+
return closePromise
|
|
60
|
+
}
|
|
61
|
+
|
|
42
62
|
export default app
|
|
@@ -11,8 +11,8 @@ import { globalErrorHandler } from './shared/errors/handler'
|
|
|
11
11
|
import { configureOpenAPI } from './shared/network/openapi'
|
|
12
12
|
import { objectEntries } from './shared/utils'
|
|
13
13
|
|
|
14
|
-
export const createApp = ({
|
|
15
|
-
const app = new Hono<AppEnv>().basePath(
|
|
14
|
+
export const createApp = ({ serverBasePath, makeDependencies }: CreateAppOptions): Hono<AppEnv> => {
|
|
15
|
+
const app = new Hono<AppEnv>().basePath(serverBasePath)
|
|
16
16
|
|
|
17
17
|
app.use('*', async (c, next) => {
|
|
18
18
|
const deps = await makeDependencies(c)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
corsConfig,
|
|
3
|
+
logBaseConfig,
|
|
4
|
+
logPrettyRawConfig,
|
|
5
|
+
logRollRawConfig,
|
|
6
|
+
logRollSchemaConfig,
|
|
7
|
+
runtimeConfig,
|
|
8
|
+
workerConfig,
|
|
9
|
+
} from '@repo/definition/backend'
|
|
10
|
+
import { getRuntimeKey } from 'hono/adapter'
|
|
11
|
+
import { flatten as flattenValiIssues, isValiError } from 'valibot'
|
|
12
|
+
import type { AppConfig } from '@/shared/app/types'
|
|
13
|
+
|
|
14
|
+
export function resolveConfig(context: Record<string, unknown>): AppConfig {
|
|
15
|
+
try {
|
|
16
|
+
const fromEnv = { context, matchContextKey: 'constantCase' as const }
|
|
17
|
+
const runtime = runtimeConfig.resolve(fromEnv)
|
|
18
|
+
const runtimeKey = getRuntimeKey()
|
|
19
|
+
const isNodejsLike = runtimeKey === 'node' || runtimeKey === 'bun'
|
|
20
|
+
const log: AppConfig['log'] = { base: logBaseConfig.resolve(fromEnv) }
|
|
21
|
+
|
|
22
|
+
if (isNodejsLike) {
|
|
23
|
+
log.roll = {
|
|
24
|
+
...logRollSchemaConfig.resolve(fromEnv),
|
|
25
|
+
...logRollRawConfig.resolve(),
|
|
26
|
+
}
|
|
27
|
+
log.pretty = logPrettyRawConfig.resolve()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
runtime: { ...runtime, isLocal: runtime.serverEnv === 'local' },
|
|
32
|
+
log,
|
|
33
|
+
worker: workerConfig.resolve(fromEnv),
|
|
34
|
+
middleware: {
|
|
35
|
+
cors: corsConfig.resolve({
|
|
36
|
+
context: { domains: context.CORS_DOMAINS },
|
|
37
|
+
matchContextKey: 'camel',
|
|
38
|
+
}),
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (isValiError(error)) {
|
|
43
|
+
throw new Error(`[resolveConfig] ${JSON.stringify(flattenValiIssues(error.issues))}`)
|
|
44
|
+
}
|
|
45
|
+
throw error
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -37,6 +37,10 @@ export const createPinoOptions = ({
|
|
|
37
37
|
}) => {
|
|
38
38
|
const pinoOptions: LoggerOptions = {
|
|
39
39
|
level: baseConfig.loggerLevel || (isLocal ? 'debug' : 'info'),
|
|
40
|
+
browser: {
|
|
41
|
+
asObject: true,
|
|
42
|
+
serialize: ['!stdSerializers.err', 'req', 'res', 'err'],
|
|
43
|
+
},
|
|
40
44
|
serializers: {
|
|
41
45
|
req: (req) => {
|
|
42
46
|
return {
|
|
@@ -1,34 +1,13 @@
|
|
|
1
1
|
/** WORKER 打包入口 */
|
|
2
|
-
import type { RunnerTaskInvocation
|
|
2
|
+
import type { RunnerTaskInvocation } from '../types'
|
|
3
3
|
import {
|
|
4
4
|
executeExampleTask as runExampleTask,
|
|
5
5
|
type ExampleRunnerTaskModel,
|
|
6
6
|
} from '@/modules/example/work-task/tasks'
|
|
7
|
-
import { isWorkerTaskBusinessError } from '../utils/business-error'
|
|
8
7
|
|
|
9
|
-
export
|
|
8
|
+
export function executeExampleTask({
|
|
10
9
|
input,
|
|
11
10
|
messagePort,
|
|
12
|
-
}: RunnerTaskInvocation<ExampleRunnerTaskModel['input']>):
|
|
13
|
-
|
|
14
|
-
> {
|
|
15
|
-
try {
|
|
16
|
-
const result = await runExampleTask(input, messagePort)
|
|
17
|
-
messagePort.postMessage({ type: 'result', data: result.data })
|
|
18
|
-
return result
|
|
19
|
-
} catch (error) {
|
|
20
|
-
if (!isWorkerTaskBusinessError(error)) throw error
|
|
21
|
-
const result = {
|
|
22
|
-
ok: false,
|
|
23
|
-
error: {
|
|
24
|
-
code: 'EXAMPLE_PROCESS_FAILED' as const,
|
|
25
|
-
message: error.message,
|
|
26
|
-
...(error.details ? { details: error.details } : {}),
|
|
27
|
-
},
|
|
28
|
-
}
|
|
29
|
-
messagePort.postMessage({ type: 'error', error: result.error })
|
|
30
|
-
return result
|
|
31
|
-
} finally {
|
|
32
|
-
messagePort.close()
|
|
33
|
-
}
|
|
11
|
+
}: RunnerTaskInvocation<ExampleRunnerTaskModel['input']>): ReturnType<typeof runExampleTask> {
|
|
12
|
+
return runExampleTask(input, messagePort).finally(() => messagePort.close())
|
|
34
13
|
}
|