@oyolincc/create 0.0.0-dev-20260918103756 → 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 -10
- 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 +21 -6
- package/templates/hono-fullstack/apps/server/src/app.ts +4 -6
- 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 +8 -4
- package/templates/hono-fullstack/apps/server/src/shared/network/validator.ts +10 -3
- 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/modules/example/{hooks.ts → hooks/api-hooks.ts} +2 -1
- package/templates/hono-fullstack/apps/stack/frontend/modules/example/stores/index.ts +3 -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 -4
- package/templates/hono-fullstack/apps/stack/tsconfig.json +7 -4
- package/templates/hono-fullstack/apps/stack/tsr.config.json +2 -2
- 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 +1 -2
- 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 +9 -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 -5
- package/templates/hono-fullstack/pnpm-workspace.yaml +8 -6
- package/templates/hono-fullstack/turbo.json +26 -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 -9
- 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 +28 -6
- package/templates/hono-server/apps/server/src/app.ts +4 -6
- 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 +8 -4
- package/templates/hono-server/apps/server/src/shared/network/validator.ts +10 -3
- 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/libs/definition/vite.config.ts +1 -1
- package/templates/hono-server/oyo.config.json +3 -1
- package/templates/hono-server/package.json +2 -3
- package/templates/hono-server/pnpm-workspace.yaml +13 -4
- package/templates/hono-server/turbo.json +26 -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 +26 -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/app.test.ts +0 -52
- 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/ExamplePage.tsx +0 -57
- 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/app.test.ts +0 -52
- package/templates/hono-server/apps/server/src/infra/work-runner/example/runner.test.ts +0 -56
|
@@ -18,19 +18,31 @@ describe('Example worker task', () => {
|
|
|
18
18
|
expect.arrayContaining([
|
|
19
19
|
expect.objectContaining({ type: 'log' }),
|
|
20
20
|
expect.objectContaining({ type: 'progress', value: 100 }),
|
|
21
|
+
expect.objectContaining({ type: 'result' }),
|
|
21
22
|
]),
|
|
22
23
|
)
|
|
23
24
|
port1.close()
|
|
24
25
|
port2.close()
|
|
25
26
|
})
|
|
26
27
|
|
|
27
|
-
it('
|
|
28
|
+
it('serializes a business exception and reports it', async () => {
|
|
28
29
|
const { port1, port2 } = new MessageChannel()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const messages: unknown[] = []
|
|
31
|
+
port1.on('message', (message) => messages.push(message))
|
|
32
|
+
const result = await executeExampleTask({ message: ' ' }, port2)
|
|
33
|
+
await new Promise<void>((resolve) => setImmediate(resolve))
|
|
34
|
+
|
|
35
|
+
expect(result).toEqual({
|
|
36
|
+
ok: false,
|
|
37
|
+
error: {
|
|
38
|
+
code: 'EXAMPLE_PROCESS_FAILED',
|
|
39
|
+
message: 'Message must not be empty',
|
|
40
|
+
details: { field: 'message' },
|
|
41
|
+
},
|
|
33
42
|
})
|
|
43
|
+
expect(messages).toEqual(
|
|
44
|
+
expect.arrayContaining([expect.objectContaining({ type: 'error' })]),
|
|
45
|
+
)
|
|
34
46
|
port1.close()
|
|
35
47
|
port2.close()
|
|
36
48
|
})
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { ProcessExampleInput, ProcessExampleOutput } from '@repo/definition/backend'
|
|
2
2
|
import { type WorkSubject } from '@/infra/work-runner/constants'
|
|
3
|
-
import type {
|
|
4
|
-
|
|
3
|
+
import type {
|
|
4
|
+
DefineRunnerTaskModel,
|
|
5
|
+
RunnerTaskResult,
|
|
6
|
+
WorkerMessagePort,
|
|
7
|
+
} from '@/infra/work-runner/types'
|
|
8
|
+
import {
|
|
9
|
+
isWorkerTaskBusinessError,
|
|
10
|
+
WorkerTaskBusinessError,
|
|
11
|
+
} from '@/infra/work-runner/utils/business-error'
|
|
5
12
|
import { workerLog, workerProgress } from '@/infra/work-runner/utils/message'
|
|
6
|
-
import type { MessagePort } from 'node:worker_threads'
|
|
7
13
|
|
|
8
14
|
export type ExampleTaskErrorCode = 'EXAMPLE_PROCESS_FAILED'
|
|
9
15
|
|
|
@@ -16,20 +22,37 @@ export type ExampleRunnerTaskModel = DefineRunnerTaskModel<
|
|
|
16
22
|
|
|
17
23
|
export async function executeExampleTask(
|
|
18
24
|
input: ExampleRunnerTaskModel['input'],
|
|
19
|
-
messagePort:
|
|
25
|
+
messagePort: WorkerMessagePort,
|
|
20
26
|
): Promise<RunnerTaskResult<ProcessExampleOutput, ExampleTaskErrorCode>> {
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
try {
|
|
28
|
+
workerLog(messagePort, 'debug', 'Example task started')
|
|
29
|
+
workerProgress(messagePort, 0, 'Validating input')
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
const original = input.message
|
|
32
|
+
const normalized = original.trim().replace(/\s+/g, ' ')
|
|
33
|
+
if (!normalized) {
|
|
34
|
+
throw new WorkerTaskBusinessError('Message must not be empty', { field: 'message' })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
workerProgress(messagePort, 100, 'Example task completed')
|
|
38
|
+
const result = {
|
|
39
|
+
ok: true,
|
|
40
|
+
data: { original, normalized, length: normalized.length },
|
|
41
|
+
} as const
|
|
42
|
+
messagePort.postMessage({ type: 'result', data: result.data })
|
|
43
|
+
return result
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (!isWorkerTaskBusinessError(error)) throw error
|
|
29
46
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
const result: RunnerTaskResult<ProcessExampleOutput, ExampleTaskErrorCode> = {
|
|
48
|
+
ok: false,
|
|
49
|
+
error: {
|
|
50
|
+
code: 'EXAMPLE_PROCESS_FAILED',
|
|
51
|
+
message: error.message,
|
|
52
|
+
...(error.details ? { details: error.details } : {}),
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
messagePort.postMessage({ type: 'error', error: result.error })
|
|
56
|
+
return result
|
|
34
57
|
}
|
|
35
58
|
}
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
WorkerConfig,
|
|
9
9
|
} from '@repo/definition/backend'
|
|
10
10
|
import type { AppWorkRunner } from '@/infra/work-runner/types'
|
|
11
|
-
import type { MiddlewareHandler } from 'hono'
|
|
11
|
+
import type { MiddlewareHandler, Context } from 'hono'
|
|
12
12
|
import type { PinoLogger as HonoPinoLogger } from 'hono-pino'
|
|
13
13
|
import type { RequestIdVariables } from 'hono/request-id'
|
|
14
14
|
|
|
@@ -30,11 +30,15 @@ export type AppConfig = {
|
|
|
30
30
|
export type AppDependencies = {
|
|
31
31
|
appConfig: AppConfig
|
|
32
32
|
loggerHandler: MiddlewareHandler<{ Variables: { logger: AppLogger } }>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
db?: unknown
|
|
33
|
+
workRunner: AppWorkRunner
|
|
34
|
+
db: unknown
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
export type AppEnv = {
|
|
39
38
|
Variables: RequestIdVariables & AppDependencies & { logger?: AppLogger }
|
|
40
39
|
}
|
|
40
|
+
|
|
41
|
+
export type CreateAppOptions = {
|
|
42
|
+
serverBasePath: string
|
|
43
|
+
makeDependencies: (c: Context<AppEnv>) => Promise<AppDependencies> | AppDependencies
|
|
44
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ValidationTargets } from 'hono'
|
|
1
|
+
import type { Env, MiddlewareHandler, ValidationTargets } from 'hono'
|
|
2
2
|
import { validator } from 'hono-openapi'
|
|
3
|
-
import { flatten, type GenericSchema } from 'valibot'
|
|
3
|
+
import { flatten, type GenericSchema, type InferInput, type InferOutput } from 'valibot'
|
|
4
4
|
import { E } from '@/shared/errors/defs'
|
|
5
5
|
|
|
6
6
|
export const generalValidator = <
|
|
@@ -9,7 +9,14 @@ export const generalValidator = <
|
|
|
9
9
|
>(
|
|
10
10
|
target: TTarget,
|
|
11
11
|
schema: TSchema,
|
|
12
|
-
)
|
|
12
|
+
): MiddlewareHandler<
|
|
13
|
+
Env,
|
|
14
|
+
string,
|
|
15
|
+
{
|
|
16
|
+
in: { [K in TTarget]: InferInput<TSchema> }
|
|
17
|
+
out: { [K in TTarget]: InferOutput<TSchema> }
|
|
18
|
+
}
|
|
19
|
+
> =>
|
|
13
20
|
validator(target, schema, (result, _c) => {
|
|
14
21
|
if (!result.success) {
|
|
15
22
|
throw E.NORMAL.VALIDATION.create({
|
|
@@ -52,14 +52,19 @@ export default defineConfig(() => {
|
|
|
52
52
|
pack: {
|
|
53
53
|
...packConfig,
|
|
54
54
|
plugins: [virtualWorkers('pack')],
|
|
55
|
+
deps: {
|
|
56
|
+
neverBundle: ['cloudflare:workers'],
|
|
57
|
+
},
|
|
55
58
|
entry: {
|
|
56
59
|
...(isServe
|
|
57
60
|
? {}
|
|
58
61
|
: {
|
|
59
|
-
|
|
62
|
+
nodejsMain: './src/adapters/nodejs/bootstrap.ts',
|
|
60
63
|
}),
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
nodejsEntry: './src/adapters/nodejs/entry.ts',
|
|
65
|
+
cloudflareEntry: './src/adapters/cloudflare/entry.ts',
|
|
66
|
+
// Enable this entry together with PiscinaWorkRunner in the Node.js adapter.
|
|
67
|
+
// 'workers/example-worker': './src/infra/work-runner/example/worker-entry.ts',
|
|
63
68
|
},
|
|
64
69
|
// deps: {
|
|
65
70
|
// neverBundle: [...builtinModules],
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/wrangler/config-schema.json",
|
|
3
|
+
"name": "repo-server-dev",
|
|
4
|
+
"main": "./src/adapters/cloudflare/entry.ts",
|
|
5
|
+
"compatibility_date": "2026-09-23",
|
|
6
|
+
"compatibility_flags": ["nodejs_compat"],
|
|
7
|
+
"dev": {
|
|
8
|
+
"port": 6464,
|
|
9
|
+
"inspector_port": 19230,
|
|
10
|
+
},
|
|
11
|
+
"observability": {
|
|
12
|
+
"logs": {
|
|
13
|
+
"enabled": true,
|
|
14
|
+
"invocation_logs": true,
|
|
15
|
+
},
|
|
16
|
+
"traces": {
|
|
17
|
+
"enabled": false,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
"d1_databases": [
|
|
21
|
+
{
|
|
22
|
+
"binding": "DB",
|
|
23
|
+
"database_name": "repo-db",
|
|
24
|
+
"database_id": "00000000-0000-0000-0000-000000000000",
|
|
25
|
+
"migrations_dir": "../../libs/db/migrations/sqlite-d1",
|
|
26
|
+
"migrations_pattern": "../../libs/db/migrations/sqlite-d1/*/migration.sql",
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import { Header } from './Header'
|
|
3
|
+
|
|
4
|
+
export function AppLayout({ children }: { children: ReactNode }) {
|
|
5
|
+
return (
|
|
6
|
+
<div className="min-h-screen bg-zinc-950 text-zinc-100">
|
|
7
|
+
<Header />
|
|
8
|
+
{children}
|
|
9
|
+
</div>
|
|
10
|
+
)
|
|
11
|
+
}
|
package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExampleForm.tsx
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { FormEvent } from 'react'
|
|
2
|
+
|
|
3
|
+
interface ExampleFormProps {
|
|
4
|
+
message: string
|
|
5
|
+
saving: boolean
|
|
6
|
+
processing: boolean
|
|
7
|
+
onMessageChange: (message: string) => void
|
|
8
|
+
onSave: () => Promise<void>
|
|
9
|
+
onProcess: () => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function ExampleForm({
|
|
13
|
+
message,
|
|
14
|
+
saving,
|
|
15
|
+
processing,
|
|
16
|
+
onMessageChange,
|
|
17
|
+
onSave,
|
|
18
|
+
onProcess,
|
|
19
|
+
}: ExampleFormProps) {
|
|
20
|
+
const submit = async (event: FormEvent) => {
|
|
21
|
+
event.preventDefault()
|
|
22
|
+
await onSave()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<form className="flex gap-2" onSubmit={submit}>
|
|
27
|
+
<input
|
|
28
|
+
className="min-w-0 flex-1 rounded border border-zinc-700 bg-zinc-900 px-3 py-2"
|
|
29
|
+
value={message}
|
|
30
|
+
onChange={(event) => onMessageChange(event.target.value)}
|
|
31
|
+
placeholder="Message"
|
|
32
|
+
/>
|
|
33
|
+
<button className="rounded bg-blue-600 px-4 py-2" disabled={!message.trim() || saving}>
|
|
34
|
+
Save
|
|
35
|
+
</button>
|
|
36
|
+
<button
|
|
37
|
+
className="rounded bg-emerald-600 px-4 py-2"
|
|
38
|
+
type="button"
|
|
39
|
+
disabled={!message.trim() || processing}
|
|
40
|
+
onClick={onProcess}>
|
|
41
|
+
Process
|
|
42
|
+
</button>
|
|
43
|
+
</form>
|
|
44
|
+
)
|
|
45
|
+
}
|
package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExampleList.tsx
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Example } from '@repo/definition/frontend'
|
|
2
|
+
|
|
3
|
+
export function ExampleList({ examples }: { examples?: Example[] }) {
|
|
4
|
+
return (
|
|
5
|
+
<ul className="grid gap-2">
|
|
6
|
+
{examples?.map((example) => (
|
|
7
|
+
<li className="rounded border border-zinc-800 p-3" key={example.id}>
|
|
8
|
+
{example.message}
|
|
9
|
+
</li>
|
|
10
|
+
))}
|
|
11
|
+
</ul>
|
|
12
|
+
)
|
|
13
|
+
}
|
package/templates/hono-fullstack/apps/stack/frontend/modules/example/{hooks.ts → hooks/api-hooks.ts}
RENAMED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
2
|
-
import { createExample, listExamples, processExample } from '
|
|
2
|
+
import { createExample, listExamples, processExample } from '../api'
|
|
3
3
|
|
|
4
4
|
export const exampleQueryKey = ['examples'] as const
|
|
5
|
+
|
|
5
6
|
export const useExamples = () => useQuery({ queryKey: exampleQueryKey, queryFn: listExamples })
|
|
6
7
|
export function useCreateExample() {
|
|
7
8
|
const queryClient = useQueryClient()
|
|
@@ -3,33 +3,43 @@
|
|
|
3
3
|
// This file was automatically generated by TanStack Router.
|
|
4
4
|
import { Route as rootRouteImport } from './routes/__root'
|
|
5
5
|
import { Route as IndexRouteImport } from './routes/index'
|
|
6
|
+
import { Route as ApiSplatRouteImport } from './routes/api/$'
|
|
6
7
|
|
|
7
8
|
const IndexRoute = IndexRouteImport.update({
|
|
8
9
|
id: '/',
|
|
9
10
|
path: '/',
|
|
10
11
|
getParentRoute: () => rootRouteImport,
|
|
11
12
|
} as any)
|
|
13
|
+
const ApiSplatRoute = ApiSplatRouteImport.update({
|
|
14
|
+
id: '/api/$',
|
|
15
|
+
path: '/api/$',
|
|
16
|
+
getParentRoute: () => rootRouteImport,
|
|
17
|
+
} as any)
|
|
12
18
|
|
|
13
19
|
export interface FileRoutesByFullPath {
|
|
14
20
|
'/': typeof IndexRoute
|
|
21
|
+
'/api/$': typeof ApiSplatRoute
|
|
15
22
|
}
|
|
16
23
|
export interface FileRoutesByTo {
|
|
17
24
|
'/': typeof IndexRoute
|
|
25
|
+
'/api/$': typeof ApiSplatRoute
|
|
18
26
|
}
|
|
19
27
|
export interface FileRoutesById {
|
|
20
28
|
__root__: typeof rootRouteImport
|
|
21
29
|
'/': typeof IndexRoute
|
|
30
|
+
'/api/$': typeof ApiSplatRoute
|
|
22
31
|
}
|
|
23
32
|
export interface FileRouteTypes {
|
|
24
33
|
fileRoutesByFullPath: FileRoutesByFullPath
|
|
25
|
-
fullPaths: '/'
|
|
34
|
+
fullPaths: '/' | '/api/$'
|
|
26
35
|
fileRoutesByTo: FileRoutesByTo
|
|
27
|
-
to: '/'
|
|
28
|
-
id: '__root__' | '/'
|
|
36
|
+
to: '/' | '/api/$'
|
|
37
|
+
id: '__root__' | '/' | '/api/$'
|
|
29
38
|
fileRoutesById: FileRoutesById
|
|
30
39
|
}
|
|
31
40
|
export interface RootRouteChildren {
|
|
32
41
|
IndexRoute: typeof IndexRoute
|
|
42
|
+
ApiSplatRoute: typeof ApiSplatRoute
|
|
33
43
|
}
|
|
34
44
|
declare module '@tanstack/react-router' {
|
|
35
45
|
interface FileRoutesByPath {
|
|
@@ -40,9 +50,16 @@ declare module '@tanstack/react-router' {
|
|
|
40
50
|
preLoaderRoute: typeof IndexRouteImport
|
|
41
51
|
parentRoute: typeof rootRouteImport
|
|
42
52
|
}
|
|
53
|
+
'/api/$': {
|
|
54
|
+
id: '/api/$'
|
|
55
|
+
path: '/api/$'
|
|
56
|
+
fullPath: '/api/$'
|
|
57
|
+
preLoaderRoute: typeof ApiSplatRouteImport
|
|
58
|
+
parentRoute: typeof rootRouteImport
|
|
59
|
+
}
|
|
43
60
|
}
|
|
44
61
|
}
|
|
45
|
-
const rootRouteChildren: RootRouteChildren = { IndexRoute }
|
|
62
|
+
const rootRouteChildren: RootRouteChildren = { IndexRoute, ApiSplatRoute }
|
|
46
63
|
export const routeTree = rootRouteImport
|
|
47
64
|
._addFileChildren(rootRouteChildren)
|
|
48
65
|
._addFileTypes<FileRouteTypes>()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
+
import { handleApiRequest } from '#server-runtime'
|
|
3
|
+
|
|
4
|
+
const serve = async ({ request }: { request: Request }) => handleApiRequest(request)
|
|
5
|
+
|
|
6
|
+
export const Route = createFileRoute('/api/$')({
|
|
7
|
+
server: {
|
|
8
|
+
handlers: {
|
|
9
|
+
GET: serve,
|
|
10
|
+
POST: serve,
|
|
11
|
+
PUT: serve,
|
|
12
|
+
PATCH: serve,
|
|
13
|
+
DELETE: serve,
|
|
14
|
+
OPTIONS: serve,
|
|
15
|
+
HEAD: serve,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
})
|
|
@@ -1,4 +1,50 @@
|
|
|
1
1
|
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
-
import {
|
|
2
|
+
import { useAtom } from 'jotai'
|
|
3
|
+
import { ErrorMessage } from '#/components/general/ErrorMessage'
|
|
4
|
+
import { AppLayout } from '#/components/layouts/AppLayout'
|
|
5
|
+
import { Page } from '#/components/layouts/Page'
|
|
6
|
+
import { PageContainer } from '#/components/layouts/PageContainer'
|
|
7
|
+
import { ExampleForm } from '#/modules/example/components/ExampleForm'
|
|
8
|
+
import { ExampleList } from '#/modules/example/components/ExampleList'
|
|
9
|
+
import { useCreateExample, useExamples, useProcessExample } from '#/modules/example/hooks/api-hooks'
|
|
10
|
+
import { exampleMessageAtom } from '#/modules/example/stores'
|
|
3
11
|
|
|
4
|
-
export const Route = createFileRoute('/')({ component:
|
|
12
|
+
export const Route = createFileRoute('/')({ component: Home })
|
|
13
|
+
|
|
14
|
+
function Home() {
|
|
15
|
+
const [message, setMessage] = useAtom(exampleMessageAtom)
|
|
16
|
+
const examples = useExamples()
|
|
17
|
+
const create = useCreateExample()
|
|
18
|
+
const process = useProcessExample()
|
|
19
|
+
|
|
20
|
+
const save = async () => {
|
|
21
|
+
await create.mutateAsync({ message })
|
|
22
|
+
setMessage('')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<AppLayout>
|
|
27
|
+
<PageContainer>
|
|
28
|
+
<Page>
|
|
29
|
+
<header>
|
|
30
|
+
<h1 className="text-3xl font-bold">Example workspace</h1>
|
|
31
|
+
<p className="text-zinc-400">Nitro mounts the independent Hono server under /api.</p>
|
|
32
|
+
</header>
|
|
33
|
+
<ExampleForm
|
|
34
|
+
message={message}
|
|
35
|
+
saving={create.isPending}
|
|
36
|
+
processing={process.isPending}
|
|
37
|
+
onMessageChange={setMessage}
|
|
38
|
+
onSave={save}
|
|
39
|
+
onProcess={() => process.mutate({ message })}
|
|
40
|
+
/>
|
|
41
|
+
{process.data && (
|
|
42
|
+
<pre className="rounded bg-zinc-900 p-4">{JSON.stringify(process.data, null, 2)}</pre>
|
|
43
|
+
)}
|
|
44
|
+
<ErrorMessage error={create.error || process.error || examples.error} />
|
|
45
|
+
<ExampleList examples={examples.data} />
|
|
46
|
+
</Page>
|
|
47
|
+
</PageContainer>
|
|
48
|
+
</AppLayout>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
@@ -4,10 +4,24 @@
|
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"dev": "
|
|
7
|
+
"dev": "pnpm dev:node",
|
|
8
|
+
"build": "pnpm build:node",
|
|
9
|
+
"preview": "pnpm preview:node",
|
|
10
|
+
"dev:node-chain": "turbo watch dev:node --filter=@repo/stack",
|
|
11
|
+
"dev:node": "DEPLOY_TARGET=node SERVER_BASE_PATH=/api oyo env server -- vp dev",
|
|
12
|
+
"build:node-chain": "turbo build:node --filter=@repo/stack",
|
|
13
|
+
"build:node": "DEPLOY_TARGET=node SERVER_BASE_PATH=/api oyo env server -- vp build",
|
|
14
|
+
"preview:node": "DEPLOY_TARGET=node SERVER_BASE_PATH=/api oyo env server -- vp preview",
|
|
15
|
+
"dev:cloudflare-chain": "turbo watch dev:cloudflare --filter=@repo/stack",
|
|
16
|
+
"dev:cloudflare": "DEPLOY_TARGET=cloudflare vp dev",
|
|
17
|
+
"build:cloudflare-chain": "turbo build:cloudflare --filter=@repo/stack",
|
|
18
|
+
"build:cloudflare": "DEPLOY_TARGET=cloudflare vp build",
|
|
19
|
+
"preview:cloudflare": "DEPLOY_TARGET=cloudflare vp preview",
|
|
20
|
+
"deploy:cloudflare": "pnpm build:cloudflare-chain && wrangler deploy",
|
|
21
|
+
"db:migrate:cloudflare:local": "wrangler d1 migrations apply DB --local --config wrangler.jsonc --persist-to ../../.wrangler/state",
|
|
22
|
+
"cf:typegen": "wrangler types",
|
|
23
|
+
"cf:typecheck": "wrangler types --check",
|
|
8
24
|
"generate-routes": "tsr generate",
|
|
9
|
-
"build": "oyo env server -- vp build",
|
|
10
|
-
"preview": "oyo env server -- vp preview",
|
|
11
25
|
"test": "vp test",
|
|
12
26
|
"check": "vp check"
|
|
13
27
|
},
|
|
@@ -24,6 +38,7 @@
|
|
|
24
38
|
"react-dom": "catalog:frontend"
|
|
25
39
|
},
|
|
26
40
|
"devDependencies": {
|
|
41
|
+
"@cloudflare/vite-plugin": "catalog:",
|
|
27
42
|
"@oyolincc/cli": "catalog:",
|
|
28
43
|
"@oyolincc/dev-config": "catalog:",
|
|
29
44
|
"@rollup/pluginutils": "catalog:",
|
|
@@ -38,6 +53,7 @@
|
|
|
38
53
|
"fast-glob": "catalog:",
|
|
39
54
|
"tailwindcss": "catalog:frontend",
|
|
40
55
|
"typescript": "catalog:",
|
|
41
|
-
"vite-plus": "catalog:"
|
|
56
|
+
"vite-plus": "catalog:",
|
|
57
|
+
"wrangler": "catalog:"
|
|
42
58
|
}
|
|
43
59
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"extends": "@oyolincc/dev-config/tsconfig.
|
|
2
|
+
"extends": "@oyolincc/dev-config/tsconfig.frontend.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
|
-
"
|
|
4
|
+
"types": ["./worker-configuration.d.ts"],
|
|
5
|
+
"jsx": "react-jsx",
|
|
5
6
|
"paths": {
|
|
6
|
-
"#/*": ["./frontend/*"]
|
|
7
|
+
"#/*": ["./frontend/*"],
|
|
8
|
+
"@/*": ["./nitro/*"]
|
|
7
9
|
}
|
|
8
10
|
},
|
|
9
|
-
"
|
|
11
|
+
"files": [],
|
|
12
|
+
"include": ["frontend", "backend", "nitro", "./*.ts", "./*.mts"]
|
|
10
13
|
}
|