@oyolincc/create 0.3.0 → 0.5.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.
- package/package.json +2 -2
- package/templates/hono-fullstack/.codegraph/.gitignore +5 -0
- package/templates/hono-fullstack/README.md +22 -1
- package/templates/hono-fullstack/_gitignore +1 -0
- package/templates/hono-fullstack/apps/server/package.json +7 -2
- package/templates/hono-fullstack/apps/server/src/adapters/cloudflare/entry.ts +4 -30
- package/templates/hono-fullstack/apps/server/src/adapters/nodejs/bootstrap.ts +20 -12
- package/templates/hono-fullstack/apps/server/src/adapters/nodejs/entry.ts +7 -57
- package/templates/hono-fullstack/apps/server/src/app.ts +37 -21
- package/templates/hono-fullstack/apps/server/src/config.ts +1 -1
- package/templates/hono-fullstack/apps/server/src/di-container.ts +51 -0
- package/templates/hono-fullstack/apps/server/src/infra/logger/getter.ts +1 -1
- package/templates/hono-fullstack/apps/server/src/infra/logger/pino.ts +21 -34
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/errors.ts +22 -0
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/pass-through/runner.ts +28 -22
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/piscina/runner.ts +11 -34
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/{example → piscina}/worker-entry.ts +6 -2
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/types.ts +2 -16
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/utils/business-error.ts +10 -5
- package/templates/hono-fullstack/apps/server/src/infra/work-runner/utils/message.ts +5 -17
- package/templates/hono-fullstack/apps/server/src/middlewares/cors.ts +16 -22
- package/templates/hono-fullstack/apps/server/src/middlewares/logger.ts +34 -0
- package/templates/hono-fullstack/apps/server/src/modules/example/module.ts +8 -0
- package/templates/hono-fullstack/apps/server/src/modules/example/queries.ts +8 -0
- package/templates/hono-fullstack/apps/server/src/modules/example/routes.ts +74 -68
- package/templates/hono-fullstack/apps/server/src/modules/example/service.test.ts +53 -0
- package/templates/hono-fullstack/apps/server/src/modules/example/service.ts +54 -0
- package/templates/hono-fullstack/apps/server/src/modules/example/types.ts +12 -0
- package/templates/hono-fullstack/apps/server/src/modules/example/work-task/tasks.test.ts +9 -35
- package/templates/hono-fullstack/apps/server/src/modules/example/work-task/tasks.ts +15 -46
- package/templates/hono-fullstack/apps/server/src/shared/errors/defs/index.ts +6 -1
- package/templates/hono-fullstack/apps/server/src/shared/errors/handler.ts +1 -1
- package/templates/hono-fullstack/apps/server/src/shared/network/openapi/index.ts +1 -1
- package/templates/hono-fullstack/apps/server/src/shared/types/app.ts +51 -0
- package/templates/hono-fullstack/apps/server/src/shared/types/db.ts +126 -0
- package/templates/hono-fullstack/apps/server/src/shared/utils/data-access/check.ts +19 -0
- package/templates/hono-fullstack/apps/server/src/shared/utils/data-access/model.ts +47 -0
- package/templates/hono-fullstack/apps/server/src/shared/utils/data-access/params.ts +105 -0
- package/templates/hono-fullstack/apps/server/src/shared/utils/data-access/query.test.ts +139 -0
- package/templates/hono-fullstack/apps/server/src/shared/utils/data-access/query.ts +236 -0
- package/templates/hono-fullstack/apps/server/vite.config.ts +2 -2
- package/templates/hono-fullstack/apps/server/wrangler.jsonc +1 -1
- package/templates/hono-fullstack/apps/stack/frontend/assets/styles.css +6 -0
- package/templates/hono-fullstack/apps/stack/frontend/components/general/ErrorMessage.tsx +3 -1
- package/templates/hono-fullstack/apps/stack/frontend/components/layouts/AppLayout.tsx +2 -1
- package/templates/hono-fullstack/apps/stack/frontend/components/layouts/Header.tsx +14 -2
- package/templates/hono-fullstack/apps/stack/frontend/components/layouts/Page.tsx +2 -1
- package/templates/hono-fullstack/apps/stack/frontend/components/layouts/PageContainer.tsx +4 -1
- package/templates/hono-fullstack/apps/stack/frontend/modules/example/api.ts +16 -9
- package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExampleForm.tsx +25 -12
- package/templates/hono-fullstack/apps/stack/frontend/modules/example/components/ExampleList.tsx +13 -4
- package/templates/hono-fullstack/apps/stack/frontend/modules/example/hooks/api-hooks.ts +21 -8
- package/templates/hono-fullstack/apps/stack/frontend/routes/__root.tsx +1 -1
- package/templates/hono-fullstack/apps/stack/frontend/routes/index.tsx +35 -12
- package/templates/hono-fullstack/apps/stack/frontend/shared/network/query-hooks.ts +33 -0
- package/templates/hono-fullstack/apps/stack/package.json +9 -4
- package/templates/hono-fullstack/apps/stack/panda.config.ts +31 -0
- package/templates/hono-fullstack/apps/stack/tsconfig.json +1 -0
- package/templates/hono-fullstack/apps/stack/turbo.json +20 -0
- package/templates/hono-fullstack/apps/stack/vite.config.ts +48 -12
- package/templates/hono-fullstack/apps/stack/wrangler.jsonc +1 -1
- package/templates/hono-fullstack/envs/.env.example.sqlite-d1 +1 -0
- package/templates/hono-fullstack/libs/db/drizzle-kit/sqlite-d1.config.ts +29 -10
- package/templates/hono-fullstack/libs/db/package.json +1 -0
- package/templates/hono-fullstack/libs/db/src/dialects/sqlite/schema/columns.ts +1 -1
- package/templates/hono-fullstack/libs/db/src/dialects/sqlite/schema/modules/examples/examples.ts +6 -3
- package/templates/hono-fullstack/libs/db/src/dialects/sqlite/schema/vo.ts +7 -1
- package/templates/hono-fullstack/libs/definition/README.md +81 -0
- package/templates/hono-fullstack/libs/definition/package.json +3 -1
- package/templates/hono-fullstack/libs/definition/src/constants/index.ts +1 -0
- package/templates/hono-fullstack/libs/definition/src/constants/pagination.ts +3 -0
- package/templates/hono-fullstack/libs/definition/src/modules/common-contracts.ts +24 -0
- package/templates/hono-fullstack/libs/definition/src/modules/example/contracts.ts +34 -0
- package/templates/hono-fullstack/libs/definition/src/modules/example/index.ts +1 -16
- package/templates/hono-fullstack/libs/definition/src/modules/index.ts +2 -0
- package/templates/hono-fullstack/libs/definition/src/modules/vo-generated-types.ts +12 -0
- package/templates/hono-fullstack/libs/ui/.storybook/main.ts +32 -0
- package/templates/hono-fullstack/libs/ui/.storybook/panda.config.ts +22 -0
- package/templates/hono-fullstack/libs/ui/.storybook/preview.tsx +79 -0
- package/templates/hono-fullstack/libs/ui/.storybook/styles.css +1 -0
- package/templates/hono-fullstack/libs/ui/.storybook/vite.config.ts +37 -0
- package/templates/hono-fullstack/libs/ui/components.json +15 -0
- package/templates/hono-fullstack/libs/ui/package.json +114 -0
- package/templates/hono-fullstack/libs/ui/panda.config.ts +41 -0
- package/templates/hono-fullstack/libs/ui/src/Tooltip.tsx +47 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/buttons/Button.tsx +80 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/buttons/CloseButton.tsx +15 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/buttons/IconButton.tsx +10 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/collections/Combobox.tsx +91 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/collections/Select.tsx +88 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/collections/TreeView.tsx +142 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/data-display/Avatar.tsx +64 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/data-display/Badge.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/data-display/Card.tsx +23 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/data-display/Clipboard.tsx +77 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/data-display/Icon.tsx +9 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/data-display/Table.tsx +51 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/data-display/Tag.tsx +23 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/data-display/Timeline.tsx +33 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/date-and-time/DatePicker.tsx +255 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/disclosure/Accordion.tsx +48 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/disclosure/Breadcrumb.tsx +50 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/disclosure/Collapsible.tsx +34 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/disclosure/Pagination.tsx +74 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/disclosure/Steps.tsx +91 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/disclosure/Tabs.tsx +37 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/feedback/Alert.tsx +52 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/feedback/Progress.tsx +41 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/feedback/ProgressCircle.tsx +40 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/feedback/Skeleton.tsx +37 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/feedback/Spinner.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/feedback/Toast.tsx +99 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/Checkbox.tsx +95 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/ColorPicker.tsx +148 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/Editable.tsx +44 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/Field.tsx +36 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/Fieldset.tsx +34 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/FileUpload.tsx +143 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/Input.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/InputAddon.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/InputGroup.tsx +61 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/NativeSelect.tsx +81 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/NumberInput.tsx +63 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/PasswordInput.tsx +76 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/PinInput.tsx +36 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/RadioCard.tsx +96 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/RadioGroup.tsx +61 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/RatingGroup.tsx +106 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/SegmentGroup.tsx +68 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/Slider.tsx +87 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/Switch.tsx +74 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/TagsInput.tsx +77 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/forms/Textarea.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/index.ts +98 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/internal/AbsoluteCenter.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/internal/Loader.tsx +69 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/internal/Span.tsx +5 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/internal/create-layout.ts +18 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/layout/Float.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/layout/Grid.tsx +17 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/layout/Group.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/layout/ScrollArea.tsx +46 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/layout/Separator.tsx +26 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/layout/Stack.tsx +54 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/overlays/Dialog.tsx +69 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/overlays/Drawer.tsx +49 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/overlays/HoverCard.tsx +37 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/overlays/Menu.tsx +74 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/overlays/OverlayManager.test.ts +124 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/overlays/OverlayManager.tsx +189 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/overlays/Popover.tsx +57 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/overlays/Tooltip.tsx +37 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/typography/Heading.tsx +6 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/typography/Link.tsx +7 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/typography/LinkOverlay.tsx +21 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/typography/Text.tsx +6 -0
- package/templates/hono-fullstack/libs/ui/src/components/atoms/utilities/VisuallyHidden.tsx +13 -0
- package/templates/hono-fullstack/libs/ui/src/hooks.ts +242 -0
- package/templates/hono-fullstack/libs/ui/src/index.ts +19 -0
- package/templates/hono-fullstack/libs/ui/src/theme/animation-styles.ts +50 -0
- package/templates/hono-fullstack/libs/ui/src/theme/breakpoints.ts +7 -0
- package/templates/hono-fullstack/libs/ui/src/theme/conditions.ts +12 -0
- package/templates/hono-fullstack/libs/ui/src/theme/containers.ts +16 -0
- package/templates/hono-fullstack/libs/ui/src/theme/global-css.ts +12 -0
- package/templates/hono-fullstack/libs/ui/src/theme/keyframes.ts +157 -0
- package/templates/hono-fullstack/libs/ui/src/theme/layer-styles.ts +11 -0
- package/templates/hono-fullstack/libs/ui/src/theme/patterns/grid.ts +51 -0
- package/templates/hono-fullstack/libs/ui/src/theme/patterns/index.ts +60 -0
- package/templates/hono-fullstack/libs/ui/src/theme/patterns/stack.ts +46 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/absolute-center.ts +38 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/accordion.ts +68 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/alert.ts +83 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/avatar.ts +155 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/badge.ts +67 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/breadcrumb.ts +69 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/button.ts +149 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/card.ts +36 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/checkbox.ts +120 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/clipboard.ts +22 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/collapsible.ts +26 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/color-picker.ts +299 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/combobox.ts +141 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/date-picker.ts +302 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/dialog.ts +191 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/drawer.ts +170 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/editable.ts +64 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/field.ts +41 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/fieldset.ts +47 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/file-upload.ts +86 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/group.ts +78 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/heading.ts +24 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/hover-card.ts +47 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/icon.ts +25 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/index.ts +120 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/input-addon.ts +51 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/input-group.ts +77 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/input.ts +99 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/link.ts +36 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/menu.ts +114 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/native-select.ts +92 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/number-input.ts +91 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/pagination.ts +9 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/pin-input.ts +33 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/popover.ts +78 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/progress-circle.ts +50 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/progress.ts +112 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/radio-card.ts +223 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/radio-group.ts +78 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/rating-group.ts +98 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/scroll-area.ts +119 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/segment-group.ts +162 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/select.ts +157 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/separator.ts +25 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/skeleton.ts +65 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/slider.ts +164 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/spinner.ts +34 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/steps.ts +162 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/switch.ts +150 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/table.ts +150 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/tabs.ts +128 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/tag.ts +114 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/tags-input.ts +201 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/text.ts +7 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/textarea.ts +90 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/timeline.ts +137 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/toast.ts +52 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/tooltip.ts +44 -0
- package/templates/hono-fullstack/libs/ui/src/theme/recipes/tree-view.ts +200 -0
- package/templates/hono-fullstack/libs/ui/src/theme/semanticTokens/colors/amber.ts +91 -0
- package/templates/hono-fullstack/libs/ui/src/theme/semanticTokens/colors/gray.ts +103 -0
- package/templates/hono-fullstack/libs/ui/src/theme/semanticTokens/colors/green.ts +88 -0
- package/templates/hono-fullstack/libs/ui/src/theme/semanticTokens/colors/index.ts +14 -0
- package/templates/hono-fullstack/libs/ui/src/theme/semanticTokens/colors/lime.ts +91 -0
- package/templates/hono-fullstack/libs/ui/src/theme/semanticTokens/colors/red.ts +88 -0
- package/templates/hono-fullstack/libs/ui/src/theme/semanticTokens/index.ts +8 -0
- package/templates/hono-fullstack/libs/ui/src/theme/semanticTokens/shadows.ts +46 -0
- package/templates/hono-fullstack/libs/ui/src/theme/text-styles.ts +82 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/animations.ts +8 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/aspect-ratio.ts +6 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/borders.ts +5 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/colors.ts +35 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/durations.ts +11 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/easings.ts +9 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/index.ts +42 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/radii.ts +13 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/sizes.ts +27 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/spacing.ts +41 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/typography.ts +86 -0
- package/templates/hono-fullstack/libs/ui/src/theme/tokens/z-index.ts +43 -0
- package/templates/hono-fullstack/libs/ui/stories/README.md +107 -0
- package/templates/hono-fullstack/libs/ui/stories/actions/Button.stories.tsx +260 -0
- package/templates/hono-fullstack/libs/ui/stories/actions/Clipboard.stories.tsx +87 -0
- package/templates/hono-fullstack/libs/ui/stories/actions/IconButton.stories.tsx +33 -0
- package/templates/hono-fullstack/libs/ui/stories/collections/Combobox.stories.tsx +334 -0
- package/templates/hono-fullstack/libs/ui/stories/collections/Select.stories.tsx +342 -0
- package/templates/hono-fullstack/libs/ui/stories/collections/TreeView.stories.tsx +252 -0
- package/templates/hono-fullstack/libs/ui/stories/color/ColorPicker.stories.tsx +217 -0
- package/templates/hono-fullstack/libs/ui/stories/date/DatePicker.stories.tsx +302 -0
- package/templates/hono-fullstack/libs/ui/stories/disclosure/Accordion.stories.tsx +105 -0
- package/templates/hono-fullstack/libs/ui/stories/disclosure/Collapsible.stories.tsx +55 -0
- package/templates/hono-fullstack/libs/ui/stories/disclosure/Steps.stories.tsx +208 -0
- package/templates/hono-fullstack/libs/ui/stories/disclosure/Tabs.stories.tsx +176 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Avatar.stories.tsx +108 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Badge.stories.tsx +90 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Card.stories.tsx +121 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Heading.stories.tsx +62 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Icon.stories.tsx +51 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Table.stories.tsx +222 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Tag.stories.tsx +168 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Text.stories.tsx +32 -0
- package/templates/hono-fullstack/libs/ui/stories/display/Timeline.stories.tsx +241 -0
- package/templates/hono-fullstack/libs/ui/stories/feedback/Alert.stories.tsx +122 -0
- package/templates/hono-fullstack/libs/ui/stories/feedback/Progress.stories.tsx +163 -0
- package/templates/hono-fullstack/libs/ui/stories/feedback/ProgressCircle.stories.tsx +176 -0
- package/templates/hono-fullstack/libs/ui/stories/feedback/Skeleton.stories.tsx +75 -0
- package/templates/hono-fullstack/libs/ui/stories/feedback/Spinner.stories.tsx +49 -0
- package/templates/hono-fullstack/libs/ui/stories/feedback/Toast.stories.tsx +145 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Checkbox.stories.tsx +281 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Editable.stories.tsx +94 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Field.stories.tsx +72 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Fieldset.stories.tsx +109 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/FileUpload.stories.tsx +115 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Form.stories.tsx +120 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Input.stories.tsx +155 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/InputGroup.stories.tsx +79 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/NativeSelect.stories.tsx +160 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/NumberInput.stories.tsx +149 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/PasswordInput.stories.tsx +141 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/PinInput.stories.tsx +155 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/RadioCard.stories.tsx +265 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/RadioGroup.stories.tsx +109 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/RatingGroup.stories.tsx +123 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/SegmentGroup.stories.tsx +130 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Slider.stories.tsx +190 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Switch.stories.tsx +124 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/TagsInput.stories.tsx +154 -0
- package/templates/hono-fullstack/libs/ui/stories/forms/Textarea.stories.tsx +148 -0
- package/templates/hono-fullstack/libs/ui/stories/layout/Grid.stories.tsx +60 -0
- package/templates/hono-fullstack/libs/ui/stories/layout/Positioning.stories.tsx +90 -0
- package/templates/hono-fullstack/libs/ui/stories/layout/ScrollArea.stories.tsx +68 -0
- package/templates/hono-fullstack/libs/ui/stories/layout/Stack.stories.tsx +87 -0
- package/templates/hono-fullstack/libs/ui/stories/navigation/Breadcrumb.stories.tsx +104 -0
- package/templates/hono-fullstack/libs/ui/stories/navigation/Link.stories.tsx +62 -0
- package/templates/hono-fullstack/libs/ui/stories/navigation/LinkBox.stories.tsx +45 -0
- package/templates/hono-fullstack/libs/ui/stories/navigation/Pagination.stories.tsx +74 -0
- package/templates/hono-fullstack/libs/ui/stories/overlays/Dialog.stories.tsx +255 -0
- package/templates/hono-fullstack/libs/ui/stories/overlays/Drawer.stories.tsx +114 -0
- package/templates/hono-fullstack/libs/ui/stories/overlays/HoverCard.stories.tsx +47 -0
- package/templates/hono-fullstack/libs/ui/stories/overlays/Menu.stories.tsx +133 -0
- package/templates/hono-fullstack/libs/ui/stories/overlays/OverlayManager.stories.tsx +206 -0
- package/templates/hono-fullstack/libs/ui/stories/overlays/Popover.stories.tsx +73 -0
- package/templates/hono-fullstack/libs/ui/stories/overlays/Tooltip.stories.tsx +114 -0
- package/templates/hono-fullstack/libs/ui/stories/tsconfig.json +14 -0
- package/templates/hono-fullstack/libs/ui/tsconfig.build.json +5 -0
- package/templates/hono-fullstack/libs/ui/tsconfig.json +13 -0
- package/templates/hono-fullstack/libs/ui/turbo.json +28 -0
- package/templates/hono-fullstack/libs/ui/vite.config.ts +33 -0
- package/templates/hono-fullstack/oyo.config.json +31 -1
- package/templates/hono-fullstack/package.json +1 -0
- package/templates/hono-fullstack/pnpm-workspace.yaml +20 -10
- package/templates/hono-fullstack/turbo.json +10 -0
- package/templates/hono-server/.codegraph/.gitignore +5 -0
- package/templates/hono-server/README.md +9 -1
- package/templates/hono-server/_gitignore +1 -0
- package/templates/hono-server/apps/server/package.json +7 -2
- package/templates/hono-server/apps/server/src/adapters/cloudflare/entry.ts +4 -30
- package/templates/hono-server/apps/server/src/adapters/nodejs/bootstrap.ts +20 -12
- package/templates/hono-server/apps/server/src/adapters/nodejs/entry.ts +7 -57
- package/templates/hono-server/apps/server/src/app.ts +37 -21
- package/templates/hono-server/apps/server/src/config.ts +1 -1
- package/templates/hono-server/apps/server/src/di-container.ts +51 -0
- package/templates/hono-server/apps/server/src/infra/logger/getter.ts +1 -1
- package/templates/hono-server/apps/server/src/infra/logger/pino.ts +21 -34
- package/templates/hono-server/apps/server/src/infra/work-runner/errors.ts +22 -0
- package/templates/hono-server/apps/server/src/infra/work-runner/pass-through/runner.ts +28 -22
- package/templates/hono-server/apps/server/src/infra/work-runner/piscina/runner.ts +11 -34
- package/templates/hono-server/apps/server/src/infra/work-runner/{example → piscina}/worker-entry.ts +6 -2
- package/templates/hono-server/apps/server/src/infra/work-runner/types.ts +2 -16
- package/templates/hono-server/apps/server/src/infra/work-runner/utils/business-error.ts +10 -5
- package/templates/hono-server/apps/server/src/infra/work-runner/utils/message.ts +5 -17
- package/templates/hono-server/apps/server/src/middlewares/cors.ts +16 -22
- package/templates/hono-server/apps/server/src/middlewares/logger.ts +34 -0
- package/templates/hono-server/apps/server/src/modules/example/module.ts +8 -0
- package/templates/hono-server/apps/server/src/modules/example/queries.ts +8 -0
- package/templates/hono-server/apps/server/src/modules/example/routes.ts +74 -68
- package/templates/hono-server/apps/server/src/modules/example/service.test.ts +53 -0
- package/templates/hono-server/apps/server/src/modules/example/service.ts +54 -0
- package/templates/hono-server/apps/server/src/modules/example/types.ts +12 -0
- package/templates/hono-server/apps/server/src/modules/example/work-task/tasks.test.ts +9 -35
- package/templates/hono-server/apps/server/src/modules/example/work-task/tasks.ts +15 -46
- package/templates/hono-server/apps/server/src/shared/errors/defs/index.ts +6 -1
- package/templates/hono-server/apps/server/src/shared/errors/handler.ts +1 -1
- package/templates/hono-server/apps/server/src/shared/network/openapi/index.ts +1 -1
- package/templates/hono-server/apps/server/src/shared/types/app.ts +51 -0
- package/templates/hono-server/apps/server/src/shared/types/db.ts +126 -0
- package/templates/hono-server/apps/server/src/shared/utils/data-access/check.ts +19 -0
- package/templates/hono-server/apps/server/src/shared/utils/data-access/model.ts +47 -0
- package/templates/hono-server/apps/server/src/shared/utils/data-access/params.ts +105 -0
- package/templates/hono-server/apps/server/src/shared/utils/data-access/query.test.ts +139 -0
- package/templates/hono-server/apps/server/src/shared/utils/data-access/query.ts +236 -0
- package/templates/hono-server/apps/server/vite.config.ts +2 -2
- package/templates/hono-server/apps/server/wrangler.jsonc +1 -1
- package/templates/hono-server/docker/README.md +1 -1
- package/templates/hono-server/envs/.env.example.sqlite-d1 +1 -0
- package/templates/hono-server/libs/db/drizzle-kit/sqlite-d1.config.ts +29 -10
- package/templates/hono-server/libs/db/package.json +1 -0
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/columns.ts +1 -1
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/modules/examples/examples.ts +6 -3
- package/templates/hono-server/libs/db/src/dialects/sqlite/schema/vo.ts +7 -1
- package/templates/hono-server/libs/definition/README.md +81 -0
- package/templates/hono-server/libs/definition/package.json +3 -1
- package/templates/hono-server/libs/definition/src/constants/index.ts +1 -0
- package/templates/hono-server/libs/definition/src/constants/pagination.ts +3 -0
- package/templates/hono-server/libs/definition/src/modules/common-contracts.ts +24 -0
- package/templates/hono-server/libs/definition/src/modules/example/contracts.ts +34 -0
- package/templates/hono-server/libs/definition/src/modules/example/index.ts +1 -16
- package/templates/hono-server/libs/definition/src/modules/index.ts +2 -0
- package/templates/hono-server/libs/definition/src/modules/vo-generated-types.ts +12 -0
- package/templates/hono-server/oyo.config.json +31 -1
- package/templates/hono-server/package.json +1 -0
- package/templates/hono-server/pnpm-workspace.yaml +9 -7
- package/templates/hono-server/turbo.json +10 -0
- package/templates/monorepo/.codegraph/.gitignore +5 -0
- package/templates/monorepo/_gitignore +1 -0
- package/templates/monorepo/oyo.config.json +7 -1
- package/templates/monorepo/pnpm-workspace.yaml +4 -4
- package/templates/monorepo/turbo.json +10 -0
- package/templates/hono-fullstack/apps/server/src/modules/example/contracts.ts +0 -9
- package/templates/hono-fullstack/apps/server/src/shared/app/types.ts +0 -44
- package/templates/hono-fullstack/apps/stack/frontend/styles.css +0 -23
- package/templates/hono-server/apps/server/src/modules/example/contracts.ts +0 -9
- package/templates/hono-server/apps/server/src/shared/app/types.ts +0 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oyolincc/create",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "@oyolincc/create",
|
|
5
5
|
"homepage": "https://github.com/oyolincc/lib#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"tsx": "4.21.0",
|
|
34
34
|
"typescript": "7.0.2",
|
|
35
35
|
"vite-plus": "0.2.8",
|
|
36
|
-
"@oyolincc/dev-config": "0.
|
|
36
|
+
"@oyolincc/dev-config": "0.2.0"
|
|
37
37
|
},
|
|
38
38
|
"createConfig": {
|
|
39
39
|
"templates": [
|
|
@@ -9,6 +9,7 @@ TanStack Start and Nitro serve the frontend while mounting the independently bui
|
|
|
9
9
|
- `apps/server`: independently buildable and startable Hono server and worker runtime.
|
|
10
10
|
- `libs/definition`: backend/frontend contracts and environment definitions.
|
|
11
11
|
- `libs/db`: SQLite/Drizzle and D1 clients, schema, relations, and manual migration commands.
|
|
12
|
+
- `libs/ui`: shared React components, Panda design system, and Storybook previews.
|
|
12
13
|
|
|
13
14
|
## Setup
|
|
14
15
|
|
|
@@ -31,7 +32,7 @@ Cloudflare runtime and binding types are generated from each runnable Worker's W
|
|
|
31
32
|
|
|
32
33
|
Before deploying, replace the placeholder D1 `database_id` and `database_name` in both Wrangler configs. Keep production variables in the Cloudflare dashboard rather than committing them.
|
|
33
34
|
|
|
34
|
-
Example tasks run in-process through `
|
|
35
|
+
Example tasks run in-process through `PassThroughRunner` by default. The complete Piscina implementation remains available: enable `PiscinaWorkRunner` in apps/server/src/di-container.ts and the adjacent worker pack entry in `apps/server/vite.config.ts` to use worker threads.
|
|
35
36
|
|
|
36
37
|
## Commands
|
|
37
38
|
|
|
@@ -45,7 +46,27 @@ Example tasks run in-process through `PassThroughWorkRunner` by default. The com
|
|
|
45
46
|
- `pnpm --filter @repo/server dev`: start Hono independently on Node.js.
|
|
46
47
|
- `pnpm --filter @repo/server dev:cloudflare`: start Hono independently on local workerd and D1.
|
|
47
48
|
- `pnpm --filter @repo/server test`: run the retained server tests.
|
|
49
|
+
- `pnpm -C apps/stack codegen`: generate the application's Panda helpers.
|
|
50
|
+
- `pnpm --filter @repo/ui storybook`: preview UI components on port 6006 without building the UI package first.
|
|
51
|
+
- `pnpm --filter @repo/ui storybook:check`: generate the preview helpers and type-check Storybook.
|
|
52
|
+
- `pnpm --filter @repo/ui storybook:build`: build the static component previews.
|
|
53
|
+
|
|
54
|
+
## UI development
|
|
55
|
+
|
|
56
|
+
The stack consumes the built `@repo/ui` design system through Panda's `designSystem` setting. Application styles live in `frontend/assets/styles.css`; document-level reset and global styles belong to the application's `panda.config.ts`. Component recipes retain the `app-` class prefix.
|
|
57
|
+
|
|
58
|
+
Stack chain commands prepare upstream packages through Turbo's `build:dev` tasks. When actively editing the UI library, its three watchers have separate responsibilities: `dev:codegen` updates local Panda helpers, `dev` updates component modules, and `dev:panda` updates the design-system manifest. Run them in separate terminals as needed; `dev` alone does not watch the complete design system.
|
|
59
|
+
|
|
60
|
+
Storybook has its own Vite and Panda configuration and generated helpers under `libs/ui/.storybook/styled-system`. See `libs/ui/stories/README.md` for preview conventions. Generated `styled-system`, `dist`, `.output`, and `storybook-static` contents are not committed.
|
|
48
61
|
|
|
49
62
|
The stack exposes health at `/api/health`, OpenAPI YAML at `/api/docs/openapi.yaml`, Swagger at `/api/swagger`, CRUD at `/api/examples`, and worker processing at `/api/examples/process`. The independently started Hono app uses `SERVER_BASE_PATH`.
|
|
50
63
|
|
|
51
64
|
The example vertical slice may be removed after replacing its definition, table, Hono routes, worker task, API hooks, and page together. Docker and CI are intentionally not included in this Fullstack template.
|
|
65
|
+
|
|
66
|
+
## Contracts and database development
|
|
67
|
+
|
|
68
|
+
Example routes validate shared contracts and call the inferDI-managed ExampleService; queries use the shared data-access layer and explicit id/list VOs. List responses contain results and pagination meta; create responses contain result and write meta. PATCH /examples/:id updates message, DELETE /examples accepts a JSON ids array, and POST /examples/process uses the configured work runner.
|
|
69
|
+
|
|
70
|
+
Run codegen:contracts and codegen:vo in libs/definition only after manually updating the DB package artifacts. These commands use IS_OVERRIDE=1 and can overwrite hand-edited contracts; review the diff and restore custom rules. See libs/definition/README.md.
|
|
71
|
+
|
|
72
|
+
IS_D1_LOCAL=1 selects the shared local metadata.sqlite database for Drizzle D1 commands. First run db:warmup:cloudflare:local in apps/server or apps/stack, then run dev:d1:push in libs/db manually. Remove IS_D1_LOCAL for remote D1 and provide Cloudflare credentials. The switch follows process.env truthiness: even the string 0 enables local mode. No schema push is run automatically.
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
"name": "@repo/server",
|
|
3
3
|
"version": "0.0.0",
|
|
4
4
|
"private": true,
|
|
5
|
-
"files": [
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
6
8
|
"type": "module",
|
|
7
9
|
"exports": {
|
|
8
10
|
"./nodejs": "./dist/nodejsEntry.mjs",
|
|
@@ -17,6 +19,7 @@
|
|
|
17
19
|
"dev:cloudflare-chain": "turbo watch dev:cloudflare --filter=@repo/server",
|
|
18
20
|
"dev:cloudflare": "wrangler dev --config wrangler.jsonc --persist-to ../../.wrangler/state",
|
|
19
21
|
"db:migrate:cloudflare:local": "wrangler d1 migrations apply DB --local --config wrangler.jsonc --persist-to ../../.wrangler/state",
|
|
22
|
+
"db:warmup:cloudflare:local": "wrangler d1 execute DB --local --config wrangler.jsonc --persist-to ../../.wrangler/state --command \"SELECT 1\"",
|
|
20
23
|
"build:node-chain": "turbo build:node --filter=@repo/server",
|
|
21
24
|
"build:node": "vp pack",
|
|
22
25
|
"cf:typegen": "wrangler types --config wrangler.jsonc",
|
|
@@ -27,7 +30,10 @@
|
|
|
27
30
|
"dependencies": {
|
|
28
31
|
"@hono/node-server": "catalog:server",
|
|
29
32
|
"@hono/standard-validator": "catalog:server",
|
|
33
|
+
"@hono/structured-logger": "catalog:server",
|
|
30
34
|
"@hono/swagger-ui": "catalog:server",
|
|
35
|
+
"@inferdi/hono": "catalog:server",
|
|
36
|
+
"@inferdi/inferdi": "catalog:",
|
|
31
37
|
"@repo/db": "workspace:*",
|
|
32
38
|
"@repo/definition": "workspace:*",
|
|
33
39
|
"@valibot/to-json-schema": "catalog:server",
|
|
@@ -37,7 +43,6 @@
|
|
|
37
43
|
"drizzle-orm": "catalog:db",
|
|
38
44
|
"hono": "catalog:server",
|
|
39
45
|
"hono-openapi": "catalog:server",
|
|
40
|
-
"hono-pino": "catalog:server",
|
|
41
46
|
"hono-problem-details": "catalog:server",
|
|
42
47
|
"ky": "catalog:shared",
|
|
43
48
|
"pino": "catalog:server",
|
|
@@ -1,36 +1,10 @@
|
|
|
1
|
-
import { createD1Client } from '@repo/db/sqlite/d1-client'
|
|
2
1
|
import { env } from 'cloudflare:workers'
|
|
3
|
-
import { getRuntimeKey } from 'hono/adapter'
|
|
4
2
|
import { createApp } from '@/app'
|
|
5
|
-
import { resolveConfig } from '@/config'
|
|
6
3
|
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
4
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
const { rootLogger, loggerHandler } = createPinoLogger({
|
|
14
|
-
isLocal: runtime.isLocal,
|
|
15
|
-
logBase: log.base,
|
|
16
|
-
runtime: getRuntimeKey(),
|
|
17
|
-
logRoll: log.roll,
|
|
18
|
-
logPretty: log.pretty,
|
|
5
|
+
const instance = createApp({
|
|
6
|
+
env: { ...env },
|
|
19
7
|
})
|
|
20
|
-
setRootLogger(
|
|
8
|
+
setRootLogger(instance.logger)
|
|
21
9
|
|
|
22
|
-
export
|
|
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
|
|
10
|
+
export default instance.app
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { serve } from '@hono/node-server'
|
|
2
|
-
import app, { closeNodeDependencies } from './entry'
|
|
3
2
|
|
|
4
|
-
function main() {
|
|
3
|
+
async function main() {
|
|
5
4
|
const port = Number(process.env.NODE_PORT)
|
|
6
5
|
if (!port || Number.isNaN(port)) {
|
|
7
6
|
throw new Error(`Invalid port: ${process.env.NODE_PORT}`)
|
|
8
7
|
}
|
|
8
|
+
const { default: app, disposeApp, rootLogger } = await import('./entry')
|
|
9
9
|
|
|
10
10
|
const server = serve(
|
|
11
11
|
{
|
|
@@ -18,8 +18,10 @@ function main() {
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
let isShuttingDown = false
|
|
21
|
+
let shutdownExitCode = 0
|
|
21
22
|
|
|
22
|
-
const gracefulShutdown = async (signal: string) => {
|
|
23
|
+
const gracefulShutdown = async (signal: string, exitCode = 0) => {
|
|
24
|
+
shutdownExitCode ||= exitCode
|
|
23
25
|
if (isShuttingDown) return
|
|
24
26
|
isShuttingDown = true
|
|
25
27
|
|
|
@@ -38,24 +40,30 @@ function main() {
|
|
|
38
40
|
})
|
|
39
41
|
console.log('✔ HTTP server successfully closed.')
|
|
40
42
|
|
|
41
|
-
await
|
|
42
|
-
console.log('✔
|
|
43
|
+
await disposeApp()
|
|
44
|
+
console.log('✔ App successfully disposed.')
|
|
43
45
|
|
|
44
46
|
console.log('Graceful shutdown completed.')
|
|
45
|
-
process.exit(
|
|
47
|
+
process.exit(shutdownExitCode)
|
|
46
48
|
} catch (err) {
|
|
47
49
|
console.error('Error during shutdown:', err)
|
|
48
50
|
process.exit(1)
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'))
|
|
53
|
-
process.on('SIGINT', () => gracefulShutdown('SIGINT'))
|
|
54
|
+
process.on('SIGTERM', () => void gracefulShutdown('SIGTERM'))
|
|
55
|
+
process.on('SIGINT', () => void gracefulShutdown('SIGINT'))
|
|
56
|
+
process.on('unhandledRejection', (reason) => {
|
|
57
|
+
rootLogger.fatal({ err: reason }, 'unhandledRejection')
|
|
58
|
+
void gracefulShutdown('unhandledRejection', 1)
|
|
59
|
+
})
|
|
60
|
+
process.on('uncaughtException', (error) => {
|
|
61
|
+
rootLogger.fatal({ err: error }, 'uncaughtException')
|
|
62
|
+
void gracefulShutdown('uncaughtException', 1)
|
|
63
|
+
})
|
|
54
64
|
}
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
main()
|
|
58
|
-
} catch (error) {
|
|
66
|
+
void main().catch((error) => {
|
|
59
67
|
console.error('[server] failed to start', error)
|
|
60
68
|
process.exit(1)
|
|
61
|
-
}
|
|
69
|
+
})
|
|
@@ -1,62 +1,12 @@
|
|
|
1
|
-
import { createSqliteClient } from '@repo/db/sqlite/sqlite'
|
|
2
|
-
import { sqliteSchemaConfig } from '@repo/definition/backend'
|
|
3
1
|
import { createApp } from '@/app'
|
|
4
|
-
import {
|
|
5
|
-
import { createPinoLogger } from '@/infra/logger/pino'
|
|
6
|
-
import { getRuntimeKey } from 'hono/adapter'
|
|
7
|
-
import type { AppDependencies, AppLogger } from '@/shared/app/types'
|
|
8
|
-
// import { PiscinaWorkRunner } from '@/infra/work-runner/piscina/runner'
|
|
9
|
-
import { PassThroughWorkRunner } from '@/infra/work-runner/pass-through/runner'
|
|
10
|
-
import { getLogger, setRootLogger } from '@/infra/logger/getter'
|
|
2
|
+
import { setRootLogger } from '@/infra/logger/getter'
|
|
11
3
|
|
|
12
|
-
|
|
13
|
-
process.
|
|
14
|
-
getLogger().error({ err: reason }, 'unhandledRejection')
|
|
15
|
-
if (isLocal) process.exit(1)
|
|
16
|
-
})
|
|
17
|
-
process.on('uncaughtException', (error) => {
|
|
18
|
-
getLogger().fatal({ err: error }, 'uncaughtException')
|
|
19
|
-
process.exit(1)
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const appConfig = resolveConfig(process.env)
|
|
24
|
-
const sqliteConfig = sqliteSchemaConfig.resolve({
|
|
25
|
-
context: process.env,
|
|
26
|
-
matchContextKey: 'constantCase',
|
|
27
|
-
})
|
|
28
|
-
const { runtime, log } = appConfig
|
|
29
|
-
const { rootLogger, loggerHandler } = createPinoLogger({
|
|
30
|
-
isLocal: runtime.isLocal,
|
|
31
|
-
logBase: log.base,
|
|
32
|
-
runtime: getRuntimeKey(),
|
|
33
|
-
logRoll: log.roll,
|
|
34
|
-
logPretty: log.pretty,
|
|
35
|
-
})
|
|
36
|
-
setRootLogger(rootLogger as unknown as AppLogger)
|
|
37
|
-
installProcessErrorHandlers(runtime.isLocal)
|
|
38
|
-
|
|
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)
|
|
43
|
-
|
|
44
|
-
let dependencies: AppDependencies | undefined
|
|
45
|
-
let closePromise: Promise<void> | undefined
|
|
46
|
-
const app = createApp({
|
|
47
|
-
serverBasePath: appConfig.runtime.serverBasePath,
|
|
48
|
-
makeDependencies: () => {
|
|
49
|
-
dependencies ||= { appConfig, loggerHandler, workRunner, db: sqliteClient.db }
|
|
50
|
-
return dependencies
|
|
51
|
-
},
|
|
4
|
+
const instance = createApp({
|
|
5
|
+
env: process.env,
|
|
52
6
|
})
|
|
7
|
+
setRootLogger(instance.logger)
|
|
53
8
|
|
|
54
|
-
export const
|
|
55
|
-
|
|
56
|
-
await workRunner.shutdown()
|
|
57
|
-
sqliteClient.close()
|
|
58
|
-
})()
|
|
59
|
-
return closePromise
|
|
60
|
-
}
|
|
9
|
+
export const rootLogger = instance.logger
|
|
10
|
+
export const disposeApp = instance.dispose
|
|
61
11
|
|
|
62
|
-
export default app
|
|
12
|
+
export default instance.app
|
|
@@ -1,43 +1,59 @@
|
|
|
1
1
|
import { Hono } from 'hono'
|
|
2
|
+
import { inferdiHono } from '@inferdi/hono'
|
|
2
3
|
import { contextStorage } from 'hono/context-storage'
|
|
3
4
|
import { csrf } from 'hono/csrf'
|
|
4
5
|
import { secureHeaders } from 'hono/secure-headers'
|
|
5
6
|
import { requestId } from 'hono/request-id'
|
|
7
|
+
import { describeRoute } from 'hono-openapi'
|
|
8
|
+
import * as v from 'valibot'
|
|
6
9
|
import { corsMiddleware } from './middlewares/cors'
|
|
7
|
-
import {
|
|
8
|
-
import type { CreateAppOptions, AppEnv } from './shared/app/types'
|
|
10
|
+
import type { CreateAppOptions, AppEnv, AppInstance } from './shared/types/app'
|
|
9
11
|
import { E } from './shared/errors/defs'
|
|
10
12
|
import { globalErrorHandler } from './shared/errors/handler'
|
|
11
|
-
import { configureOpenAPI } from './shared/network/openapi'
|
|
12
|
-
import {
|
|
13
|
+
import { configureOpenAPI, jsonResponse, OpenApiTags } from './shared/network/openapi'
|
|
14
|
+
import { successJson } from './shared/network/utils'
|
|
15
|
+
import { loggerMiddleware } from './middlewares/logger'
|
|
16
|
+
import { createDIContainer } from './di-container'
|
|
17
|
+
import { flushPino } from './infra/logger/pino'
|
|
18
|
+
import { routes as exampleRoutes } from './modules/example/routes'
|
|
13
19
|
|
|
14
|
-
export const createApp = ({ serverBasePath,
|
|
15
|
-
const
|
|
20
|
+
export const createApp = ({ serverBasePath, env }: CreateAppOptions): AppInstance => {
|
|
21
|
+
const diContainer = createDIContainer({ env })
|
|
22
|
+
const rootLogger = diContainer.get('rootLogger')
|
|
23
|
+
const appConfig = diContainer.get('appConfig')
|
|
24
|
+
const app = new Hono<AppEnv>().basePath(serverBasePath ?? appConfig.runtime.serverBasePath)
|
|
16
25
|
|
|
17
|
-
app.use('*', async (c, next) => {
|
|
18
|
-
const deps = await makeDependencies(c)
|
|
19
|
-
objectEntries(deps).forEach(([key, value]) => c.set(key, value))
|
|
20
|
-
await next()
|
|
21
|
-
})
|
|
22
26
|
app.use(contextStorage())
|
|
23
27
|
app.use('*', requestId())
|
|
24
|
-
app.use('*',
|
|
25
|
-
|
|
26
|
-
await loggerHandler(c as never, async () => {
|
|
27
|
-
c.get('logger')?.assign({ reqId: c.get('requestId') })
|
|
28
|
-
await next()
|
|
29
|
-
})
|
|
30
|
-
})
|
|
28
|
+
app.use('*', loggerMiddleware(rootLogger))
|
|
29
|
+
app.use('*', inferdiHono({ container: diContainer }))
|
|
31
30
|
app.use('*', secureHeaders())
|
|
32
|
-
app.use('*', corsMiddleware())
|
|
31
|
+
app.use('*', corsMiddleware(appConfig.middleware.cors))
|
|
33
32
|
app.use('*', csrf())
|
|
34
33
|
|
|
35
|
-
app.
|
|
34
|
+
app.get(
|
|
35
|
+
'/health',
|
|
36
|
+
describeRoute({
|
|
37
|
+
operationId: 'getHealth',
|
|
38
|
+
tags: [OpenApiTags.System],
|
|
39
|
+
summary: 'Health check',
|
|
40
|
+
responses: { 200: jsonResponse(v.object({ data: v.object({ status: v.string() }) })) },
|
|
41
|
+
}),
|
|
42
|
+
(c) => successJson(c, { status: 'ok' }),
|
|
43
|
+
)
|
|
44
|
+
app.route('/examples', exampleRoutes)
|
|
36
45
|
configureOpenAPI(app)
|
|
37
46
|
|
|
38
47
|
app.notFound(() => {
|
|
39
48
|
throw E.NORMAL.NOT_FOUND.create()
|
|
40
49
|
})
|
|
41
50
|
app.onError(globalErrorHandler)
|
|
42
|
-
return
|
|
51
|
+
return {
|
|
52
|
+
app,
|
|
53
|
+
logger: rootLogger,
|
|
54
|
+
dispose: async () => {
|
|
55
|
+
await diContainer.dispose()
|
|
56
|
+
await flushPino(rootLogger)
|
|
57
|
+
},
|
|
58
|
+
}
|
|
43
59
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from '@repo/definition/backend'
|
|
10
10
|
import { getRuntimeKey } from 'hono/adapter'
|
|
11
11
|
import { flatten as flattenValiIssues, isValiError } from 'valibot'
|
|
12
|
-
import type { AppConfig } from '@/shared/app
|
|
12
|
+
import type { AppConfig } from '@/shared/types/app'
|
|
13
13
|
|
|
14
14
|
export function resolveConfig(context: Record<string, unknown>): AppConfig {
|
|
15
15
|
try {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getRuntimeKey } from 'hono/adapter'
|
|
2
|
+
import { Container } from '@inferdi/inferdi'
|
|
3
|
+
import { resolveConfig } from './config'
|
|
4
|
+
import { createPino } from './infra/logger/pino'
|
|
5
|
+
import { sqliteSchemaConfig } from '@repo/definition/backend'
|
|
6
|
+
import { createD1Client, type D1Binding } from '@repo/db/sqlite/d1-client'
|
|
7
|
+
import { createSqliteClient } from '@repo/db/sqlite/sqlite'
|
|
8
|
+
import type { Database } from './shared/types/db'
|
|
9
|
+
import { exampleModule } from './modules/example/module'
|
|
10
|
+
import { PassThroughRunner } from './infra/work-runner/pass-through/runner'
|
|
11
|
+
// import { PiscinaWorkRunner } from './infra/work-runner/piscina/runner'
|
|
12
|
+
import type { AppWorkRunner } from './infra/work-runner/types'
|
|
13
|
+
|
|
14
|
+
export const createDIContainer = ({ env }: { env: Record<string, unknown> }) => {
|
|
15
|
+
const runtimeKey = getRuntimeKey()
|
|
16
|
+
return new Container()
|
|
17
|
+
.registerValue('appConfig', resolveConfig(env))
|
|
18
|
+
.registerFactory('rootLogger', (c) => {
|
|
19
|
+
const { runtime, log } = c.get('appConfig')
|
|
20
|
+
return createPino({
|
|
21
|
+
isLocal: runtime.isLocal,
|
|
22
|
+
logConfig: log,
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
.registerFactory('database', (): Database => {
|
|
26
|
+
if (runtimeKey === 'workerd') return createD1Client(env.DB as D1Binding)
|
|
27
|
+
|
|
28
|
+
const { dbPath } = sqliteSchemaConfig.resolve({
|
|
29
|
+
context: env,
|
|
30
|
+
matchContextKey: 'constantCase',
|
|
31
|
+
})
|
|
32
|
+
const client = createSqliteClient(dbPath)
|
|
33
|
+
return {
|
|
34
|
+
db: client.db,
|
|
35
|
+
[Symbol.dispose]() {
|
|
36
|
+
client.close()
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
.registerFactory('workRunner', (_c) => {
|
|
41
|
+
// Enable together with the worker pack entry in vite.config.ts.
|
|
42
|
+
// const runner: AppWorkRunner = PiscinaWorkRunner.getInstance(_c.get('appConfig').worker)
|
|
43
|
+
const runner: AppWorkRunner = new PassThroughRunner()
|
|
44
|
+
return Object.assign(runner, {
|
|
45
|
+
[Symbol.asyncDispose]: () => runner.shutdown(),
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
.use(exampleModule)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type DIContainer = ReturnType<typeof createDIContainer>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'
|
|
2
2
|
import { isAbsolute, join, resolve } from 'node:path'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import type { AppConfig } from '@/shared/app/types'
|
|
3
|
+
import { getRuntimeKey } from 'hono/adapter'
|
|
4
|
+
import pino, { type Logger, type LoggerOptions } from 'pino'
|
|
5
|
+
import type { LogConfig } from '@/shared/types/app'
|
|
7
6
|
import { serializeErr } from '@/shared/errors/log'
|
|
8
7
|
|
|
9
8
|
// const pinoInstance = pino({
|
|
@@ -33,7 +32,7 @@ export const createPinoOptions = ({
|
|
|
33
32
|
baseConfig,
|
|
34
33
|
}: {
|
|
35
34
|
isLocal: boolean
|
|
36
|
-
baseConfig:
|
|
35
|
+
baseConfig: LogConfig['base']
|
|
37
36
|
}) => {
|
|
38
37
|
const pinoOptions: LoggerOptions = {
|
|
39
38
|
level: baseConfig.loggerLevel || (isLocal ? 'debug' : 'info'),
|
|
@@ -69,38 +68,28 @@ export const createPinoOptions = ({
|
|
|
69
68
|
return pinoOptions
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
export const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
logRoll,
|
|
77
|
-
logPretty,
|
|
78
|
-
}: {
|
|
79
|
-
isLocal: boolean
|
|
80
|
-
logBase: AppConfig['log']['base']
|
|
81
|
-
runtime: Runtime
|
|
82
|
-
logRoll?: AppConfig['log']['roll']
|
|
83
|
-
logPretty?: AppConfig['log']['pretty']
|
|
84
|
-
}) => {
|
|
85
|
-
const pinoOptions = createPinoOptions({ isLocal, baseConfig: logBase })
|
|
71
|
+
export const createPino = ({ isLocal, logConfig }: { isLocal: boolean; logConfig: LogConfig }) => {
|
|
72
|
+
const runtime = getRuntimeKey()
|
|
73
|
+
const { base, roll, pretty } = logConfig
|
|
74
|
+
const pinoOptions = createPinoOptions({ isLocal, baseConfig: base })
|
|
86
75
|
const level = pinoOptions.level
|
|
87
76
|
if (runtime === 'node' || runtime === 'bun') {
|
|
88
|
-
if (isLocal &&
|
|
77
|
+
if (isLocal && pretty) {
|
|
89
78
|
try {
|
|
90
79
|
createRequire(import.meta.url).resolve('pino-pretty')
|
|
91
|
-
pinoOptions.transport = { target: 'pino-pretty', level, options:
|
|
80
|
+
pinoOptions.transport = { target: 'pino-pretty', level, options: pretty }
|
|
92
81
|
} catch {
|
|
93
82
|
console.warn('[logger] pino-pretty is not installed; falling back to JSON stdout')
|
|
94
83
|
}
|
|
95
|
-
} else if (
|
|
96
|
-
const { loggerDir, loggerFileBase } =
|
|
84
|
+
} else if (roll) {
|
|
85
|
+
const { loggerDir, loggerFileBase } = roll
|
|
97
86
|
pinoOptions.transport = {
|
|
98
87
|
targets: [
|
|
99
88
|
{
|
|
100
89
|
target: 'pino-roll',
|
|
101
90
|
level,
|
|
102
91
|
options: {
|
|
103
|
-
...
|
|
92
|
+
...roll,
|
|
104
93
|
file: join(
|
|
105
94
|
isAbsolute(loggerDir) ? loggerDir : resolve(process.cwd(), loggerDir),
|
|
106
95
|
loggerFileBase,
|
|
@@ -112,15 +101,13 @@ export const createPinoLogger = ({
|
|
|
112
101
|
}
|
|
113
102
|
}
|
|
114
103
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
},
|
|
104
|
+
return pino(pinoOptions)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const flushPino = async (logger: Logger) => {
|
|
108
|
+
const runtime = getRuntimeKey()
|
|
109
|
+
if (runtime !== 'node' && runtime !== 'bun') return
|
|
110
|
+
await new Promise<void>((resolve, reject) => {
|
|
111
|
+
logger.flush((error) => (error ? reject(error) : resolve()))
|
|
124
112
|
})
|
|
125
|
-
return { rootLogger, loggerHandler }
|
|
126
113
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { hasProp } from '@/shared/utils'
|
|
2
2
|
import { WorkerErrorCode } from './constants'
|
|
3
3
|
import type { RunnerTaskError, RunnerTaskErrorDetails } from './types'
|
|
4
|
+
import { isWorkerTaskBusinessError } from './utils/business-error'
|
|
4
5
|
|
|
5
6
|
const workerErrorCodes = Object.values(WorkerErrorCode)
|
|
6
7
|
|
|
@@ -38,3 +39,24 @@ export function isWorkerTaskError(error: unknown): error is WorkerTaskError {
|
|
|
38
39
|
workerErrorCodes.includes(error.code as WorkerErrorCode))
|
|
39
40
|
)
|
|
40
41
|
}
|
|
42
|
+
|
|
43
|
+
export function serializeWorkerTaskError(error: unknown): RunnerTaskError<WorkerErrorCode> {
|
|
44
|
+
if (isWorkerTaskError(error)) return error.serialize()
|
|
45
|
+
if (isWorkerTaskBusinessError(error)) {
|
|
46
|
+
return new WorkerTaskError(
|
|
47
|
+
WorkerErrorCode.TASK_INTERNAL,
|
|
48
|
+
error.message,
|
|
49
|
+
error.cause.details,
|
|
50
|
+
error.cause.cause,
|
|
51
|
+
).serialize()
|
|
52
|
+
}
|
|
53
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
54
|
+
return new WorkerTaskError(WorkerErrorCode.TASK_ABORTED, error.message, undefined).serialize()
|
|
55
|
+
}
|
|
56
|
+
return new WorkerTaskError(
|
|
57
|
+
WorkerErrorCode.UNKNOWN,
|
|
58
|
+
'Worker task failed unexpectedly',
|
|
59
|
+
undefined,
|
|
60
|
+
error,
|
|
61
|
+
).serialize()
|
|
62
|
+
}
|
|
@@ -1,41 +1,47 @@
|
|
|
1
|
-
import { executeExampleTask } from '
|
|
1
|
+
import { executeExampleTask as runExampleTask } from '@/modules/example/work-task/tasks'
|
|
2
2
|
import { getLogger } from '@/infra/logger/getter'
|
|
3
3
|
import { WorkSubject } from '../constants'
|
|
4
|
+
import { serializeWorkerTaskError } from '../errors'
|
|
4
5
|
import type {
|
|
5
6
|
AppWorkRunner,
|
|
7
|
+
RunnerTaskInput,
|
|
6
8
|
RunnerTaskParams,
|
|
7
9
|
RunnerTaskRunOptions,
|
|
8
10
|
RunnerTaskRunResult,
|
|
9
|
-
WorkerMessage,
|
|
10
|
-
WorkerMessagePort,
|
|
11
11
|
} from '../types'
|
|
12
|
-
import { handleWorkerMessage } from '../utils/message'
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
close() {},
|
|
21
|
-
}
|
|
13
|
+
const taskMap = {
|
|
14
|
+
[WorkSubject.PROCESS_EXAMPLE]: runExampleTask,
|
|
15
|
+
} satisfies {
|
|
16
|
+
[TSubject in WorkSubject]?: (
|
|
17
|
+
input: RunnerTaskInput<TSubject>,
|
|
18
|
+
) => Promise<RunnerTaskRunResult<TSubject>>
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
export class
|
|
21
|
+
export class PassThroughRunner implements AppWorkRunner {
|
|
25
22
|
async run<TSubject extends WorkSubject>(
|
|
26
|
-
|
|
23
|
+
task: RunnerTaskParams<TSubject>,
|
|
27
24
|
options?: RunnerTaskRunOptions,
|
|
28
25
|
): Promise<RunnerTaskRunResult<TSubject>> {
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
const targetTask = taskMap[task.subject]
|
|
27
|
+
if (!targetTask) {
|
|
28
|
+
throw new Error(`[PassThroughRunner] task name not found: ${String(task.subject)}`)
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
const logger = getLogger().child({ subject: task.subject })
|
|
32
|
+
logger.debug('Task executing in current thread')
|
|
33
|
+
let result: RunnerTaskRunResult<TSubject>
|
|
34
|
+
try {
|
|
35
|
+
options?.signal?.throwIfAborted()
|
|
36
|
+
result = (await targetTask(task.input)) as RunnerTaskRunResult<TSubject>
|
|
37
|
+
} catch (error) {
|
|
38
|
+
result = { ok: false, error: serializeWorkerTaskError(error) }
|
|
39
|
+
}
|
|
40
|
+
logger[result.ok ? 'info' : 'error'](
|
|
41
|
+
{ subject: task.subject, ok: result.ok },
|
|
42
|
+
`Task ${result.ok ? 'completed' : 'failed'}`,
|
|
43
|
+
)
|
|
44
|
+
return result
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
async shutdown(): Promise<void> {}
|