@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.
Files changed (135) hide show
  1. package/package.json +1 -1
  2. package/templates/hono-fullstack/.vscode/launch.json +14 -3
  3. package/templates/hono-fullstack/.vscode/settings.json +3 -1
  4. package/templates/hono-fullstack/AGENTS.md +7 -0
  5. package/templates/hono-fullstack/README.md +28 -14
  6. package/templates/hono-fullstack/_gitignore +4 -0
  7. package/templates/hono-fullstack/apps/server/.dev.vars.example +9 -0
  8. package/templates/hono-fullstack/apps/server/package.json +17 -10
  9. package/templates/hono-fullstack/apps/server/src/adapters/cloudflare/entry.ts +36 -0
  10. package/templates/hono-fullstack/apps/server/src/adapters/nodejs/bootstrap.ts +3 -6
  11. package/templates/hono-fullstack/apps/server/src/adapters/nodejs/entry.ts +21 -6
  12. package/templates/hono-fullstack/apps/server/src/app.ts +4 -6
  13. package/templates/hono-fullstack/apps/server/src/config.ts +47 -0
  14. package/templates/hono-fullstack/apps/server/src/infra/logger/pino.ts +4 -0
  15. package/templates/hono-fullstack/apps/server/src/infra/work-runner/example/worker-entry.ts +4 -25
  16. package/templates/hono-fullstack/apps/server/src/infra/work-runner/pass-through/runner.ts +42 -0
  17. package/templates/{hono-server/apps/server/src/infra/work-runner/example → hono-fullstack/apps/server/src/infra/work-runner/piscina}/runner.ts +9 -9
  18. package/templates/hono-fullstack/apps/server/src/infra/work-runner/types.ts +7 -2
  19. package/templates/hono-fullstack/apps/server/src/infra/work-runner/utils/message.ts +7 -4
  20. package/templates/hono-fullstack/apps/server/src/modules/example/routes.ts +3 -5
  21. package/templates/hono-fullstack/apps/server/src/modules/example/work-task/tasks.test.ts +17 -5
  22. package/templates/hono-fullstack/apps/server/src/modules/example/work-task/tasks.ts +38 -15
  23. package/templates/hono-fullstack/apps/server/src/shared/app/types.ts +8 -4
  24. package/templates/hono-fullstack/apps/server/src/shared/network/validator.ts +10 -3
  25. package/templates/hono-fullstack/apps/server/tsconfig.json +1 -0
  26. package/templates/hono-fullstack/apps/server/vite.config.ts +8 -3
  27. package/templates/hono-fullstack/apps/server/wrangler.jsonc +29 -0
  28. package/templates/hono-fullstack/apps/stack/backend/cloudflare.ts +5 -0
  29. package/templates/hono-fullstack/apps/stack/backend/node.ts +3 -0
  30. package/templates/hono-fullstack/apps/stack/frontend/components/general/ErrorMessage.tsx +4 -0
  31. package/templates/hono-fullstack/apps/stack/frontend/components/layouts/AppLayout.tsx +11 -0
  32. package/templates/hono-fullstack/apps/stack/frontend/components/layouts/Header.tsx +7 -0
  33. package/templates/hono-fullstack/apps/stack/frontend/components/layouts/Page.tsx +5 -0
  34. package/templates/hono-fullstack/apps/stack/frontend/components/layouts/PageContainer.tsx +5 -0
  35. package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExampleForm.tsx +45 -0
  36. package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExampleList.tsx +13 -0
  37. package/templates/hono-fullstack/apps/stack/frontend/modules/example/{hooks.ts → hooks/api-hooks.ts} +2 -1
  38. package/templates/hono-fullstack/apps/stack/frontend/modules/example/stores/index.ts +3 -0
  39. package/templates/hono-fullstack/apps/stack/frontend/routeTree.gen.ts +21 -4
  40. package/templates/hono-fullstack/apps/stack/frontend/routes/api/$.ts +18 -0
  41. package/templates/hono-fullstack/apps/stack/frontend/routes/index.tsx +48 -2
  42. package/templates/hono-fullstack/apps/stack/frontend/vite-env.d.ts +5 -0
  43. package/templates/hono-fullstack/apps/stack/package.json +20 -4
  44. package/templates/hono-fullstack/apps/stack/tsconfig.json +7 -4
  45. package/templates/hono-fullstack/apps/stack/tsr.config.json +2 -2
  46. package/templates/hono-fullstack/apps/stack/vite.config.ts +75 -26
  47. package/templates/hono-fullstack/apps/stack/wrangler.jsonc +20 -0
  48. package/templates/hono-fullstack/envs/.env.example.server +1 -1
  49. package/templates/hono-fullstack/envs/.env.example.sqlite +1 -2
  50. package/templates/hono-fullstack/envs/.env.example.sqlite-d1 +3 -0
  51. package/templates/hono-fullstack/libs/db/drizzle-kit/sqlite-d1.config.ts +22 -0
  52. package/templates/hono-fullstack/libs/db/package.json +9 -6
  53. package/templates/hono-fullstack/libs/db/src/dialects/sqlite/d1-client.ts +12 -0
  54. package/templates/hono-fullstack/libs/db/src/dialects/sqlite/schema/columns.ts +5 -0
  55. package/templates/hono-fullstack/libs/db/src/dialects/sqlite/schema/modules/examples/examples.ts +2 -2
  56. package/templates/hono-fullstack/libs/db/vite.config.ts +1 -0
  57. package/templates/hono-fullstack/libs/definition/src/configs/defs/runtime.ts +1 -0
  58. package/templates/hono-fullstack/libs/definition/src/configs/defs/sqlite.ts +16 -3
  59. package/templates/hono-fullstack/oyo.config.json +2 -1
  60. package/templates/hono-fullstack/package.json +1 -5
  61. package/templates/hono-fullstack/pnpm-workspace.yaml +8 -6
  62. package/templates/hono-fullstack/turbo.json +26 -3
  63. package/templates/hono-fullstack/vite.config.ts +1 -0
  64. package/templates/hono-server/.vscode/launch.json +7 -3
  65. package/templates/hono-server/.vscode/settings.json +3 -1
  66. package/templates/hono-server/AGENTS.md +7 -0
  67. package/templates/hono-server/README.md +25 -12
  68. package/templates/hono-server/_gitignore +4 -0
  69. package/templates/hono-server/apps/server/.dev.vars.example +9 -0
  70. package/templates/hono-server/apps/server/package.json +18 -9
  71. package/templates/hono-server/apps/server/src/adapters/cloudflare/entry.ts +36 -0
  72. package/templates/hono-server/apps/server/src/adapters/nodejs/bootstrap.ts +3 -3
  73. package/templates/hono-server/apps/server/src/adapters/nodejs/entry.ts +28 -6
  74. package/templates/hono-server/apps/server/src/app.ts +4 -6
  75. package/templates/hono-server/apps/server/src/config.ts +47 -0
  76. package/templates/hono-server/apps/server/src/infra/logger/pino.ts +4 -0
  77. package/templates/hono-server/apps/server/src/infra/work-runner/example/worker-entry.ts +4 -25
  78. package/templates/hono-server/apps/server/src/infra/work-runner/pass-through/runner.ts +42 -0
  79. package/templates/{hono-fullstack/apps/server/src/infra/work-runner/example → hono-server/apps/server/src/infra/work-runner/piscina}/runner.ts +9 -9
  80. package/templates/hono-server/apps/server/src/infra/work-runner/types.ts +7 -2
  81. package/templates/hono-server/apps/server/src/infra/work-runner/utils/message.ts +7 -4
  82. package/templates/hono-server/apps/server/src/modules/example/contracts.ts +4 -0
  83. package/templates/hono-server/apps/server/src/modules/example/routes.ts +32 -5
  84. package/templates/hono-server/apps/server/src/modules/example/work-task/tasks.test.ts +17 -5
  85. package/templates/hono-server/apps/server/src/modules/example/work-task/tasks.ts +38 -15
  86. package/templates/hono-server/apps/server/src/shared/app/types.ts +8 -4
  87. package/templates/hono-server/apps/server/src/shared/network/validator.ts +10 -3
  88. package/templates/hono-server/apps/server/tsconfig.json +1 -0
  89. package/templates/hono-server/apps/server/vite.config.ts +8 -3
  90. package/templates/hono-server/apps/server/wrangler.jsonc +29 -0
  91. package/templates/hono-server/docker/server.Dockerfile +3 -5
  92. package/templates/hono-server/envs/.env.example.server +1 -1
  93. package/templates/hono-server/envs/.env.example.sqlite +1 -0
  94. package/templates/hono-server/envs/.env.example.sqlite-d1 +3 -0
  95. package/templates/hono-server/libs/db/drizzle-kit/sqlite-d1.config.ts +22 -0
  96. package/templates/hono-server/libs/db/drizzle-kit/sqlite.config.ts +22 -0
  97. package/templates/hono-server/libs/db/package.json +42 -0
  98. package/templates/hono-server/libs/db/src/dialects/sqlite/client.ts +35 -0
  99. package/templates/hono-server/libs/db/src/dialects/sqlite/d1-client.ts +12 -0
  100. package/templates/hono-server/libs/db/src/dialects/sqlite/schema/columns.ts +37 -0
  101. package/templates/hono-server/libs/db/src/dialects/sqlite/schema/index.ts +7 -0
  102. package/templates/hono-server/libs/db/src/dialects/sqlite/schema/modules/examples/examples.ts +22 -0
  103. package/templates/hono-server/libs/db/src/dialects/sqlite/schema/relations.ts +5 -0
  104. package/templates/hono-server/libs/db/src/dialects/sqlite/schema/tables.ts +5 -0
  105. package/templates/hono-server/libs/db/src/dialects/sqlite/schema/types.ts +7 -0
  106. package/templates/hono-server/libs/db/src/dialects/sqlite/schema/vo.ts +1 -0
  107. package/templates/hono-server/libs/db/src/dialects/sqlite/utils.ts +8 -0
  108. package/templates/hono-server/libs/db/src/shared/types.ts +26 -0
  109. package/templates/hono-server/libs/db/tsconfig.json +10 -0
  110. package/templates/hono-server/libs/db/vite.config.ts +22 -0
  111. package/templates/hono-server/libs/definition/src/configs/defs/runtime.ts +1 -0
  112. package/templates/hono-server/libs/definition/src/configs/defs/sqlite.ts +26 -0
  113. package/templates/hono-server/libs/definition/src/configs/index.ts +1 -0
  114. package/templates/hono-server/libs/definition/vite.config.ts +1 -1
  115. package/templates/hono-server/oyo.config.json +3 -1
  116. package/templates/hono-server/package.json +2 -3
  117. package/templates/hono-server/pnpm-workspace.yaml +13 -4
  118. package/templates/hono-server/turbo.json +26 -3
  119. package/templates/hono-server/vite.config.ts +1 -0
  120. package/templates/monorepo/.vscode/launch.json +0 -3
  121. package/templates/monorepo/.vscode/settings.json +3 -1
  122. package/templates/monorepo/AGENTS.md +7 -0
  123. package/templates/monorepo/_gitignore +4 -0
  124. package/templates/monorepo/pnpm-workspace.yaml +6 -3
  125. package/templates/monorepo/turbo.json +26 -3
  126. package/templates/monorepo/vite.config.ts +1 -0
  127. package/templates/hono-fullstack/apps/server/src/adapters/nodejs/config.ts +0 -53
  128. package/templates/hono-fullstack/apps/server/src/app.test.ts +0 -52
  129. package/templates/hono-fullstack/apps/server/src/infra/work-runner/example/runner.test.ts +0 -56
  130. package/templates/hono-fullstack/apps/stack/frontend/modules/example/ExamplePage.tsx +0 -57
  131. package/templates/hono-fullstack/apps/stack/nitro/handlers/hono.ts +0 -1
  132. package/templates/hono-fullstack/apps/stack/nitro/plugins/hono.ts +0 -9
  133. package/templates/hono-server/apps/server/src/adapters/nodejs/config.ts +0 -53
  134. package/templates/hono-server/apps/server/src/app.test.ts +0 -52
  135. package/templates/hono-server/apps/server/src/infra/work-runner/example/runner.test.ts +0 -56
@@ -1,13 +1,36 @@
1
1
  {
2
2
  "$schema": "https://turbo.build/schema.json",
3
3
  "tasks": {
4
- "build": {
4
+ "dev": {
5
5
  "dependsOn": ["^build"],
6
- "outputs": ["dist/**", ".output/**"]
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": {
16
+ "dependsOn": ["^build"],
17
+ "env": ["DEPLOY_TARGET"],
9
18
  "cache": false,
10
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/**"]
11
34
  }
12
35
  }
13
36
  }
@@ -2,6 +2,7 @@ import { defineConfig } from 'vite-plus'
2
2
  import { lintConfig, fmtConfig } from '@oyolincc/dev-config'
3
3
 
4
4
  export default defineConfig({
5
+ create: { defaultTemplate: '@oyolincc' },
5
6
  staged: {
6
7
  '*': 'vp check --fix',
7
8
  },
@@ -1,53 +0,0 @@
1
- import type { AppConfig } from '@/shared/app/types'
2
- import {
3
- corsConfig,
4
- logBaseConfig,
5
- logPrettyRawConfig,
6
- logRollRawConfig,
7
- logRollSchemaConfig,
8
- runtimeConfig,
9
- workerConfig,
10
- type WorkerConfig,
11
- } from '@repo/definition/backend'
12
- import { flatten as flattenValiIssues, isValiError } from 'valibot'
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 logBaseParsed = logBaseConfig.resolve(fromEnv)
19
- const logRollSchemaParsed = logRollSchemaConfig.resolve(fromEnv)
20
- const worker = workerConfig.resolve(fromEnv)
21
- const cors = corsConfig.resolve({
22
- context: { domains: context.CORS_DOMAINS },
23
- matchContextKey: 'camel',
24
- })
25
-
26
- return {
27
- runtime: { ...runtime, isLocal: runtime.serverEnv === 'local' },
28
- log: {
29
- base: logBaseParsed,
30
- roll: { ...logRollSchemaParsed, ...logRollRawConfig.resolve() },
31
- pretty: logPrettyRawConfig.resolve(),
32
- },
33
- middleware: { cors },
34
- worker,
35
- }
36
- } catch (error) {
37
- if (isValiError(error)) {
38
- throw new Error(`[resolveAppConfig] ${JSON.stringify(flattenValiIssues(error.issues))}`)
39
- }
40
- throw error
41
- }
42
- }
43
-
44
- export function resolveWorkerConfig(context: Record<string, unknown>): WorkerConfig {
45
- try {
46
- return workerConfig.resolve({ context, matchContextKey: 'constantCase' })
47
- } catch (error) {
48
- if (isValiError(error)) {
49
- throw new Error(`[resolveWorkerConfig] ${JSON.stringify(flattenValiIssues(error.issues))}`)
50
- }
51
- throw error
52
- }
53
- }
@@ -1,52 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
- import { createApp } from './app'
3
- import type { AppDependencies, AppLogger } from './shared/app/types'
4
-
5
- const logger = new Proxy(
6
- { assign() {} },
7
- { get: (target, key) => Reflect.get(target, key) || (() => {}) },
8
- ) as AppLogger
9
- const dependencies = {
10
- appConfig: { middleware: { cors: { domains: ['*'] } } },
11
- loggerHandler: async (c: any, next: () => Promise<void>) => {
12
- c.set('logger', logger)
13
- await next()
14
- },
15
- exampleWorkRunner: {
16
- async run(task: any) {
17
- const original = task.input.message
18
- const normalized = original.trim().replace(/\s+/g, ' ')
19
- return { ok: true as const, data: { original, normalized, length: normalized.length } }
20
- },
21
- async shutdown() {},
22
- },
23
- } as unknown as AppDependencies
24
-
25
- describe('HTTP contracts', () => {
26
- const app = createApp(() => dependencies)
27
-
28
- it('wraps successful responses in data', async () => {
29
- const response = await app.request('/health')
30
- expect(response.status).toBe(200)
31
- await expect(response.json()).resolves.toEqual({ data: { status: 'ok' } })
32
- })
33
-
34
- it('returns Problem Details for missing routes', async () => {
35
- const response = await app.request('/missing')
36
- expect(response.status).toBe(404)
37
- await expect(response.json()).resolves.toMatchObject({ status: 404, type: 'NORMAL.NOT_FOUND' })
38
- })
39
-
40
- it('returns validation Problem Details with status 422', async () => {
41
- const response = await app.request('/examples/process', {
42
- method: 'POST',
43
- headers: { 'content-type': 'application/json' },
44
- body: JSON.stringify({ message: '' }),
45
- })
46
- expect(response.status).toBe(422)
47
- await expect(response.json()).resolves.toMatchObject({
48
- status: 422,
49
- type: 'NORMAL.VALIDATION',
50
- })
51
- })
52
- })
@@ -1,56 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from 'vite-plus/test'
2
- import { WorkerErrorCode, WorkSubject } from '../constants'
3
- import { ExampleWorkRunner } from './runner'
4
-
5
- vi.mock('@/infra/logger/getter', () => ({
6
- getLogger: () =>
7
- new Proxy({ assign() {} }, { get: (target, key) => Reflect.get(target, key) || (() => {}) }),
8
- }))
9
- vi.mock('virtual:workers', () => ({ default: '/tmp' }))
10
- vi.mock('piscina', () => ({
11
- default: class PiscinaMock {
12
- idleThreads = 1
13
- threads: unknown[] = []
14
- queueSize = 0
15
- options = { maxQueue: 1 }
16
-
17
- run() {
18
- throw new Error('An aborted task must not reach the worker pool')
19
- }
20
-
21
- async close() {}
22
- },
23
- }))
24
-
25
- const config = {
26
- minThreads: 1,
27
- maxThreads: 1,
28
- concurrentTasksPerWorker: 1,
29
- maxQueue: 1,
30
- workerTaskTimeoutMs: 1_000,
31
- }
32
-
33
- describe('ExampleWorkRunner cancellation', () => {
34
- let runner: ExampleWorkRunner | undefined
35
-
36
- afterEach(async () => {
37
- await runner?.shutdown()
38
- runner = undefined
39
- })
40
-
41
- it('returns the task-aborted error model for an aborted signal', async () => {
42
- runner = ExampleWorkRunner.getInstance(config)
43
- const controller = new AbortController()
44
- controller.abort()
45
-
46
- await expect(
47
- runner.run(
48
- { subject: WorkSubject.PROCESS_EXAMPLE, input: { message: 'hello' } },
49
- { signal: controller.signal },
50
- ),
51
- ).resolves.toMatchObject({
52
- ok: false,
53
- error: { code: WorkerErrorCode.TASK_ABORTED },
54
- })
55
- })
56
- })
@@ -1,57 +0,0 @@
1
- import { useState, type FormEvent } from 'react'
2
- import { useCreateExample, useExamples, useProcessExample } from './hooks'
3
-
4
- export function ExamplePage() {
5
- const [message, setMessage] = useState('')
6
- const examples = useExamples()
7
- const create = useCreateExample()
8
- const process = useProcessExample()
9
-
10
- const submit = async (event: FormEvent) => {
11
- event.preventDefault()
12
- await create.mutateAsync({ message })
13
- setMessage('')
14
- }
15
-
16
- return (
17
- <main className="mx-auto flex min-h-screen max-w-2xl flex-col gap-6 p-8">
18
- <header>
19
- <h1 className="text-3xl font-bold">Example workspace</h1>
20
- <p className="text-zinc-400">Nitro mounts the independent Hono server under /api.</p>
21
- </header>
22
- <form className="flex gap-2" onSubmit={submit}>
23
- <input
24
- className="min-w-0 flex-1 rounded border border-zinc-700 bg-zinc-900 px-3 py-2"
25
- value={message}
26
- onChange={(event) => setMessage(event.target.value)}
27
- placeholder="Message"
28
- />
29
- <button
30
- className="rounded bg-blue-600 px-4 py-2"
31
- disabled={!message.trim() || create.isPending}>
32
- Save
33
- </button>
34
- <button
35
- className="rounded bg-emerald-600 px-4 py-2"
36
- type="button"
37
- disabled={!message.trim() || process.isPending}
38
- onClick={() => process.mutate({ message })}>
39
- Process
40
- </button>
41
- </form>
42
- {process.data && (
43
- <pre className="rounded bg-zinc-900 p-4">{JSON.stringify(process.data, null, 2)}</pre>
44
- )}
45
- {(create.error || process.error || examples.error) && (
46
- <p className="text-red-400">{String(create.error || process.error || examples.error)}</p>
47
- )}
48
- <ul className="grid gap-2">
49
- {examples.data?.map((example) => (
50
- <li className="rounded border border-zinc-800 p-3" key={example.id}>
51
- {example.message}
52
- </li>
53
- ))}
54
- </ul>
55
- </main>
56
- )
57
- }
@@ -1 +0,0 @@
1
- export { default } from '@repo/server/node'
@@ -1,9 +0,0 @@
1
- import { definePlugin } from 'nitro'
2
- import { exampleWorkRunner, sqliteClient } from '@repo/server/node'
3
-
4
- export default definePlugin((nitro) => {
5
- nitro.hooks.hook('close', async () => {
6
- await exampleWorkRunner.shutdown()
7
- sqliteClient.close()
8
- })
9
- })
@@ -1,53 +0,0 @@
1
- import type { AppConfig } from '@/shared/app/types'
2
- import {
3
- corsConfig,
4
- logBaseConfig,
5
- logPrettyRawConfig,
6
- logRollRawConfig,
7
- logRollSchemaConfig,
8
- runtimeConfig,
9
- workerConfig,
10
- type WorkerConfig,
11
- } from '@repo/definition/backend'
12
- import { flatten as flattenValiIssues, isValiError } from 'valibot'
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 logBaseParsed = logBaseConfig.resolve(fromEnv)
19
- const logRollSchemaParsed = logRollSchemaConfig.resolve(fromEnv)
20
- const worker = workerConfig.resolve(fromEnv)
21
- const cors = corsConfig.resolve({
22
- context: { domains: context.CORS_DOMAINS },
23
- matchContextKey: 'camel',
24
- })
25
-
26
- return {
27
- runtime: { ...runtime, isLocal: runtime.serverEnv === 'local' },
28
- log: {
29
- base: logBaseParsed,
30
- roll: { ...logRollSchemaParsed, ...logRollRawConfig.resolve() },
31
- pretty: logPrettyRawConfig.resolve(),
32
- },
33
- middleware: { cors },
34
- worker,
35
- }
36
- } catch (error) {
37
- if (isValiError(error)) {
38
- throw new Error(`[resolveAppConfig] ${JSON.stringify(flattenValiIssues(error.issues))}`)
39
- }
40
- throw error
41
- }
42
- }
43
-
44
- export function resolveWorkerConfig(context: Record<string, unknown>): WorkerConfig {
45
- try {
46
- return workerConfig.resolve({ context, matchContextKey: 'constantCase' })
47
- } catch (error) {
48
- if (isValiError(error)) {
49
- throw new Error(`[resolveWorkerConfig] ${JSON.stringify(flattenValiIssues(error.issues))}`)
50
- }
51
- throw error
52
- }
53
- }
@@ -1,52 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
- import { createApp } from './app'
3
- import type { AppDependencies, AppLogger } from './shared/app/types'
4
-
5
- const logger = new Proxy(
6
- { assign() {} },
7
- { get: (target, key) => Reflect.get(target, key) || (() => {}) },
8
- ) as AppLogger
9
- const dependencies = {
10
- appConfig: { middleware: { cors: { domains: ['*'] } } },
11
- loggerHandler: async (c: any, next: () => Promise<void>) => {
12
- c.set('logger', logger)
13
- await next()
14
- },
15
- exampleWorkRunner: {
16
- async run(task: any) {
17
- const original = task.input.message
18
- const normalized = original.trim().replace(/\s+/g, ' ')
19
- return { ok: true as const, data: { original, normalized, length: normalized.length } }
20
- },
21
- async shutdown() {},
22
- },
23
- } as unknown as AppDependencies
24
-
25
- describe('HTTP contracts', () => {
26
- const app = createApp(() => dependencies)
27
-
28
- it('wraps successful responses in data', async () => {
29
- const response = await app.request('/health')
30
- expect(response.status).toBe(200)
31
- await expect(response.json()).resolves.toEqual({ data: { status: 'ok' } })
32
- })
33
-
34
- it('returns Problem Details for missing routes', async () => {
35
- const response = await app.request('/missing')
36
- expect(response.status).toBe(404)
37
- await expect(response.json()).resolves.toMatchObject({ status: 404, type: 'NORMAL.NOT_FOUND' })
38
- })
39
-
40
- it('returns validation Problem Details with status 422', async () => {
41
- const response = await app.request('/examples/process', {
42
- method: 'POST',
43
- headers: { 'content-type': 'application/json' },
44
- body: JSON.stringify({ message: '' }),
45
- })
46
- expect(response.status).toBe(422)
47
- await expect(response.json()).resolves.toMatchObject({
48
- status: 422,
49
- type: 'NORMAL.VALIDATION',
50
- })
51
- })
52
- })
@@ -1,56 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from 'vite-plus/test'
2
- import { WorkerErrorCode, WorkSubject } from '../constants'
3
- import { ExampleWorkRunner } from './runner'
4
-
5
- vi.mock('@/infra/logger/getter', () => ({
6
- getLogger: () =>
7
- new Proxy({ assign() {} }, { get: (target, key) => Reflect.get(target, key) || (() => {}) }),
8
- }))
9
- vi.mock('virtual:workers', () => ({ default: '/tmp' }))
10
- vi.mock('piscina', () => ({
11
- default: class PiscinaMock {
12
- idleThreads = 1
13
- threads: unknown[] = []
14
- queueSize = 0
15
- options = { maxQueue: 1 }
16
-
17
- run() {
18
- throw new Error('An aborted task must not reach the worker pool')
19
- }
20
-
21
- async close() {}
22
- },
23
- }))
24
-
25
- const config = {
26
- minThreads: 1,
27
- maxThreads: 1,
28
- concurrentTasksPerWorker: 1,
29
- maxQueue: 1,
30
- workerTaskTimeoutMs: 1_000,
31
- }
32
-
33
- describe('ExampleWorkRunner cancellation', () => {
34
- let runner: ExampleWorkRunner | undefined
35
-
36
- afterEach(async () => {
37
- await runner?.shutdown()
38
- runner = undefined
39
- })
40
-
41
- it('returns the task-aborted error model for an aborted signal', async () => {
42
- runner = ExampleWorkRunner.getInstance(config)
43
- const controller = new AbortController()
44
- controller.abort()
45
-
46
- await expect(
47
- runner.run(
48
- { subject: WorkSubject.PROCESS_EXAMPLE, input: { message: 'hello' } },
49
- { signal: controller.signal },
50
- ),
51
- ).resolves.toMatchObject({
52
- ok: false,
53
- error: { code: WorkerErrorCode.TASK_ABORTED },
54
- })
55
- })
56
- })