@forinda/kickjs-cli 8.4.0 → 8.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/{project-docs-Ck3uzaEG.mjs → agent-docs-BFOgLbXq.mjs} +81 -71
  2. package/dist/agent-docs-BFOgLbXq.mjs.map +1 -0
  3. package/dist/{project-docs-8d5GNDIw.mjs → agent-docs-BU1rORKA.mjs} +75 -67
  4. package/dist/{build-Bw_SFnBG.mjs → build-CdIpRyfy.mjs} +3 -3
  5. package/dist/{build-Bw_SFnBG.mjs.map → build-CdIpRyfy.mjs.map} +1 -1
  6. package/dist/{build-BrNa6gYZ.mjs → build-DlfIkjcw.mjs} +2 -2
  7. package/dist/{builtins-DHjV84lv.mjs → builtins-CfAXBoIM.mjs} +2 -2
  8. package/dist/{builtins-CNZ4QP-z.mjs → builtins-CmuUgcIq.mjs} +36 -31
  9. package/dist/cli.mjs +2 -2
  10. package/dist/config-SvlcF3Ls.mjs +12 -0
  11. package/dist/config-ndsVdO8u.mjs +13 -0
  12. package/dist/config-ndsVdO8u.mjs.map +1 -0
  13. package/dist/{doctor-DzqvC6jF.mjs → doctor-D3RMXkxE.mjs} +6 -6
  14. package/dist/{doctor-DzqvC6jF.mjs.map → doctor-D3RMXkxE.mjs.map} +1 -1
  15. package/dist/fs-DdNMcW_P.mjs +12 -0
  16. package/dist/fs-DdNMcW_P.mjs.map +1 -0
  17. package/dist/fs-v57MCgpH.mjs +11 -0
  18. package/dist/fullstack-DOufUeMv.mjs +95 -0
  19. package/dist/fullstack-LJwhodT-.mjs +96 -0
  20. package/dist/fullstack-LJwhodT-.mjs.map +1 -0
  21. package/dist/index.d.mts +15 -24
  22. package/dist/index.d.mts.map +1 -1
  23. package/dist/index.mjs +2 -2
  24. package/dist/{plugin-C11bSFtE.mjs → plugin-Dighdqh-.mjs} +2 -2
  25. package/dist/{plugin-BdN4scZR.mjs → plugin-Dn67elEZ.mjs} +2 -2
  26. package/dist/project-AXCA1hD9.mjs +45 -0
  27. package/dist/project-Cb_NLUWI.mjs +46 -0
  28. package/dist/project-Cb_NLUWI.mjs.map +1 -0
  29. package/dist/{project-root-DORRVmte.mjs → project-root-C7TrLJlZ.mjs} +3 -3
  30. package/dist/{project-root-DORRVmte.mjs.map → project-root-C7TrLJlZ.mjs.map} +1 -1
  31. package/dist/{project-root-D_rrQbpy.mjs → project-root-Dgvy5kYG.mjs} +2 -2
  32. package/dist/{prompts-DHHDYxLL.mjs → prompts-CSATvwXw.mjs} +2 -2
  33. package/dist/{prompts-DHHDYxLL.mjs.map → prompts-CSATvwXw.mjs.map} +1 -1
  34. package/dist/{rolldown-runtime-LCdccCoI.mjs → rolldown-runtime-BhxEEqxa.mjs} +1 -1
  35. package/dist/{run-plugins-DSYGn4AC.mjs → run-plugins-Cf_6BgGZ.mjs} +34 -29
  36. package/dist/run-plugins-Cf_6BgGZ.mjs.map +1 -0
  37. package/dist/{typegen-Bv9EzadE.mjs → typegen-97E_RYNp.mjs} +4 -4
  38. package/dist/typegen-CYhFNfIu.mjs +132 -0
  39. package/dist/{typegen-COTKpuqW.mjs.map → typegen-CYhFNfIu.mjs.map} +1 -1
  40. package/dist/{types-CW4qiwB1.mjs → types-lHwt_SNI.mjs} +1 -1
  41. package/package.json +10 -9
  42. package/templates/base/feature.json +18 -0
  43. package/templates/base/files/README.md +61 -0
  44. package/templates/base/files/_dot_editorconfig +13 -0
  45. package/templates/base/files/_dot_env +2 -0
  46. package/templates/base/files/_dot_env.example +2 -0
  47. package/templates/base/files/_dot_env.test +9 -0
  48. package/templates/base/files/_dot_env.test.example +11 -0
  49. package/templates/base/files/_dot_gitattributes +18 -0
  50. package/templates/base/files/_dot_gitignore +14 -0
  51. package/templates/base/files/_dot_oxfmtrc.json +9 -0
  52. package/templates/base/files/kick.config.ts +58 -0
  53. package/templates/base/files/src/modules/hello/hello.controller.ts +26 -0
  54. package/templates/base/files/src/modules/hello/hello.module.ts +21 -0
  55. package/templates/base/files/src/modules/hello/hello.service.ts +12 -0
  56. package/templates/base/files/src/modules/index.ts +7 -0
  57. package/templates/base/files/tsconfig.json +21 -0
  58. package/templates/base/files/vite.config.ts +31 -0
  59. package/templates/base/files/vitest.config.ts +18 -0
  60. package/templates/feature-devtools/feature.json +13 -0
  61. package/templates/feature-queue/feature.json +16 -0
  62. package/templates/feature-queue/files/_dot_env.append +2 -0
  63. package/templates/feature-queue/files/_dot_env.example.append +2 -0
  64. package/templates/feature-swagger/feature.json +16 -0
  65. package/templates/feature-ws/feature.json +13 -0
  66. package/templates/fullstack-root/files/_dot_gitignore +8 -0
  67. package/templates/fullstack-root/files/netlify.toml +13 -0
  68. package/templates/fullstack-root/files/vercel.json +5 -0
  69. package/templates/host-config/files/netlify.toml +6 -0
  70. package/templates/host-config/files/vercel.json +5 -0
  71. package/templates/runtime-express/feature.json +22 -0
  72. package/templates/runtime-fastify/feature.json +13 -0
  73. package/templates/runtime-h3/feature.json +13 -0
  74. package/templates/schema-valibot/feature.json +3 -0
  75. package/templates/schema-valibot/files/src/config/index.ts +41 -0
  76. package/templates/schema-yup/feature.json +3 -0
  77. package/templates/schema-yup/files/src/config/index.ts +43 -0
  78. package/templates/schema-zod/feature.json +3 -0
  79. package/templates/schema-zod/files/src/config/index.ts +41 -0
  80. package/templates/server-fullstack/feature.json +13 -0
  81. package/templates/template-minimal/feature.json +10 -0
  82. package/templates/template-minimal/files/src/index.ts +17 -0
  83. package/templates/template-rest/feature.json +10 -0
  84. package/templates/template-rest/files/src/index.ts +28 -0
  85. package/templates/web-kick/files/web/index.html +12 -0
  86. package/templates/web-kick/files/web/src/App.tsx +45 -0
  87. package/templates/web-kick/files/web/src/api.ts +14 -0
  88. package/templates/web-kick/files/web/src/main.tsx +9 -0
  89. package/templates/web-kick/files/web/tsconfig.json +15 -0
  90. package/templates/web-kick/files/web/vite.config.ts +13 -0
  91. package/dist/agent-docs-BIYv2Od-.mjs +0 -11
  92. package/dist/agent-docs-DWRW_0cn.mjs +0 -12
  93. package/dist/agent-docs-DWRW_0cn.mjs.map +0 -1
  94. package/dist/config-B6LRxtE1.mjs +0 -13
  95. package/dist/config-B6LRxtE1.mjs.map +0 -1
  96. package/dist/config-DIH8bQUO.mjs +0 -12
  97. package/dist/fullstack-BwdcyVD3.mjs +0 -195
  98. package/dist/fullstack-BwdcyVD3.mjs.map +0 -1
  99. package/dist/fullstack-CkAO5DhE.mjs +0 -194
  100. package/dist/project--WiWkarb.mjs +0 -450
  101. package/dist/project-JoccwqS2.mjs +0 -451
  102. package/dist/project-JoccwqS2.mjs.map +0 -1
  103. package/dist/project-docs-8d5GNDIw.mjs.map +0 -1
  104. package/dist/run-plugins-DSYGn4AC.mjs.map +0 -1
  105. package/dist/typegen-COTKpuqW.mjs +0 -132
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @forinda/kickjs-cli v8.4.0
2
+ * @forinda/kickjs-cli v8.6.0
3
3
  *
4
4
  * Copyright (c) Felix Orinda
5
5
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forinda/kickjs-cli",
3
- "version": "8.4.0",
3
+ "version": "8.6.0",
4
4
  "description": "CLI for KickJS — project scaffolding, DDD module generation, dev/build/start",
5
5
  "keywords": [
6
6
  "kickjs",
@@ -29,30 +29,31 @@
29
29
  },
30
30
  "files": [
31
31
  "bin.js",
32
- "dist"
32
+ "dist",
33
+ "templates"
33
34
  ],
34
35
  "dependencies": {
35
36
  "@clack/prompts": "^1.8.0",
36
37
  "commander": "^15.0.0",
37
38
  "glob": "^13.0.6",
38
39
  "jiti": "^2.7.0",
39
- "oxc-parser": "^0.150.0",
40
- "oxfmt": "^0.68.0",
40
+ "oxc-parser": "^0.151.0",
41
+ "oxfmt": "^0.70.0",
41
42
  "picocolors": "^1.1.1",
42
43
  "pluralize": "^8.0.0",
43
- "@forinda/kickjs-cli-kit": "0.1.2",
44
- "@forinda/kickjs-db": "7.3.0",
45
- "@forinda/kickjs": "8.6.0"
44
+ "@forinda/kickjs": "8.7.0",
45
+ "@forinda/kickjs-db": "7.4.0",
46
+ "@forinda/kickjs-cli-kit": "0.1.2"
46
47
  },
47
48
  "devDependencies": {
48
49
  "@swc/core": "^1.16.2",
49
- "@types/node": "^26.6.1",
50
+ "@types/node": "^26.6.2",
50
51
  "@types/pg": "^8.23.1",
51
52
  "@types/pluralize": "^0.0.33",
52
53
  "@typescript/typescript6": "^6.0.2",
53
54
  "pg": "^8.23.0",
54
55
  "typescript": "^7.0.2",
55
- "vite": "^8.3.0",
56
+ "vite": "^8.3.1",
56
57
  "vitest": "^5.0.1",
57
58
  "@forinda/kickjs-ai": "8.0.0"
58
59
  },
@@ -0,0 +1,18 @@
1
+ {
2
+ "dependencies": ["@forinda/kickjs", "@forinda/kickjs-schema", "dotenv", "reflect-metadata"],
3
+ "devDependencies": [
4
+ "@forinda/kickjs-cli",
5
+ "@forinda/kickjs-testing",
6
+ "@forinda/kickjs-vite",
7
+ "@types/supertest",
8
+ "@swc/core",
9
+ "@types/node",
10
+ "unplugin-swc",
11
+ "vite",
12
+ "supertest",
13
+ "vitest",
14
+ "typescript",
15
+ "oxfmt",
16
+ "oxlint"
17
+ ]
18
+ }
@@ -0,0 +1,61 @@
1
+ # {{name}}
2
+
3
+ A **{{templateLabel}}** built with [KickJS](https://kickjs.app/) — a decorator-driven Node.js framework for TypeScript that runs on Express, Fastify, or h3 (swap the engine in one line).
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ {{packageManager}} install
9
+ kick dev
10
+ ```
11
+
12
+ ## Scripts
13
+
14
+ | Command | Description |
15
+ | ------------------------------------ | ------------------------------------ |
16
+ | `kick dev` | Start dev server with Vite HMR |
17
+ | `kick build` | Production build |
18
+ | `kick start` | Run production build |
19
+ | `{{packageManager}} run test` | Run tests with Vitest |
20
+ | `kick g module <name>` | Generate a DDD module |
21
+ | `kick g scaffold <name> <fields...>` | Generate CRUD from field definitions |
22
+ | `kick add <package>` | Add a KickJS package |
23
+
24
+ ## Project Structure
25
+
26
+ ```
27
+ src/
28
+ ├── index.ts # Application entry point
29
+ ├── modules/ # Feature modules (controllers, services, repos)
30
+ │ └── index.ts # Module registry
31
+ └── ...
32
+ ```
33
+
34
+ ## Packages
35
+
36
+ {{packages}}
37
+
38
+ ## Adding Features
39
+
40
+ ```bash
41
+ kick add swagger # OpenAPI documentation
42
+ kick add ws # WebSocket support
43
+ kick add queue # Background job processing
44
+ kick add --list # Show all available packages
45
+ ```
46
+
47
+ For email, scheduled tasks, multi-tenancy, OpenTelemetry, GraphQL, and notifications use the BYO recipes in the [KickJS guides](https://kickjs.app/guide/) — they wire the upstream library through `defineAdapter()` / `definePlugin()` directly, so you keep control of the integration.
48
+
49
+ ## Environment Variables
50
+
51
+ Copy `.env.example` to `.env` and configure:
52
+
53
+ | Variable | Default | Description |
54
+ | ---------- | ------------- | ----------- |
55
+ | `PORT` | `3000` | Server port |
56
+ | `NODE_ENV` | `development` | Environment |
57
+
58
+ ## Learn More
59
+
60
+ - [KickJS Documentation](https://kickjs.app/)
61
+ - [CLI Reference](https://kickjs.app/api/cli.html)
@@ -0,0 +1,13 @@
1
+ # https://editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ indent_style = space
6
+ indent_size = 2
7
+ end_of_line = lf
8
+ charset = utf-8
9
+ trim_trailing_whitespace = true
10
+ insert_final_newline = true
11
+
12
+ [*.md]
13
+ trim_trailing_whitespace = false
@@ -0,0 +1,2 @@
1
+ PORT=3000
2
+ NODE_ENV=development
@@ -0,0 +1,2 @@
1
+ PORT=3000
2
+ NODE_ENV=development
@@ -0,0 +1,9 @@
1
+ # Read INSTEAD of .env when NODE_ENV=test (or under vitest).
2
+ # No fallback to .env — declare here everything the suite needs, so a
3
+ # missing var fails the run instead of silently resolving to your dev value.
4
+ #
5
+ # Not committed. Add new keys to .env.test.example too, with placeholder
6
+ # values — never real endpoints or credentials.
7
+ NODE_ENV=test
8
+ PORT=0
9
+ LOG_LEVEL=silent
@@ -0,0 +1,11 @@
1
+ # Template for .env.test. Copy it and fill in your machine's values:
2
+ # cp .env.test.example .env.test
3
+ # Read INSTEAD of .env when NODE_ENV=test (or under vitest).
4
+ # No fallback to .env — declare here everything the suite needs, so a
5
+ # missing var fails the run instead of silently resolving to your dev value.
6
+ #
7
+ # This file is committed; .env.test is not. Keep the two in step, with
8
+ # placeholder values here — never real endpoints or credentials.
9
+ NODE_ENV=test
10
+ PORT=0
11
+ LOG_LEVEL=silent
@@ -0,0 +1,18 @@
1
+ # Auto-detect text files and normalise line endings to LF
2
+ * text=auto eol=lf
3
+
4
+ # Explicitly mark generated / binary files
5
+ *.png binary
6
+ *.jpg binary
7
+ *.jpeg binary
8
+ *.gif binary
9
+ *.ico binary
10
+ *.woff binary
11
+ *.woff2 binary
12
+ *.ttf binary
13
+ *.eot binary
14
+
15
+ # Lock files — treat as generated
16
+ pnpm-lock.yaml -diff linguist-generated
17
+ yarn.lock -diff linguist-generated
18
+ package-lock.json -diff linguist-generated
@@ -0,0 +1,14 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ # Machine-specific: each developer's test env differs (database names, ports).
5
+ # The shared template is the committed `.env.test.example`.
6
+ .env.test
7
+ *.local
8
+ coverage/
9
+ .DS_Store
10
+ *.tsbuildinfo
11
+ .kickjs/
12
+ # Platform build output — written by `kick build:netlify` / `kick build:vercel`.
13
+ .netlify/
14
+ .vercel/
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "./node_modules/oxfmt/configuration_schema.json",
3
+ "semi": false,
4
+ "singleQuote": true,
5
+ "trailingComma": "all",
6
+ "printWidth": 100,
7
+ "tabWidth": 2,
8
+ "ignorePatterns": ["**/dist/", "**/.kickjs/", "**/node_modules/"]
9
+ }
@@ -0,0 +1,58 @@
1
+ import { defineConfig } from '@forinda/kickjs-cli'
2
+
3
+ export default defineConfig({
4
+ pattern: '{{template}}',
5
+ // The HTTP engine this app boots on (matches `bootstrap({ runtime })` in
6
+ // src/index.ts). Dep-aware commands read it: `kick add upload` installs the
7
+ // engine's multipart driver, `kick doctor` checks the engine peers, and
8
+ // `kick typegen` flips the runtime escape-hatch types to this engine.
9
+ runtime: '{{runtime}}',
10
+ // Pinned so `kick add` and other dep-installing commands always use the
11
+ // project's intended package manager, regardless of which lockfile exists.
12
+ packageManager: '{{packageManager}}',
13
+ modules: {
14
+ dir: 'src/modules',
15
+ // @kick:repo
16
+ pluralize: true,
17
+ },
18
+
19
+ // `kick typegen` populates `.kickjs/types/` so `Ctx<KickRoutes.X['method']>`
20
+ // resolves to fully-typed params/body/query. Auto-runs on `kick dev`.
21
+ // `'kickjs-schema'` routes inference through `InferSchemaOutput` so the
22
+ // typegen works for any wrapped schema (Zod / Valibot / Yup). Switch
23
+ // to `'zod'` if you ship Zod schemas without `fromZod()` wrapping, or
24
+ // set `schemaValidator: false` to skip schema-driven body typing.
25
+ typegen: {
26
+ schemaValidator: 'kickjs-schema',
27
+ // @kick:typegen-option
28
+ },
29
+
30
+ commands: [
31
+ {
32
+ name: 'test',
33
+ description: 'Run tests with Vitest',
34
+ steps: 'vitest run',
35
+ },
36
+ {
37
+ name: 'lint',
38
+ description: 'Lint with oxlint',
39
+ steps: 'oxlint src/',
40
+ },
41
+ {
42
+ name: 'format',
43
+ description: 'Format code with oxfmt',
44
+ steps: 'oxfmt src/',
45
+ },
46
+ {
47
+ name: 'format:check',
48
+ description: 'Check formatting without writing',
49
+ steps: 'oxfmt --check src/',
50
+ },
51
+ {
52
+ name: 'ci:check',
53
+ description: 'Run typecheck + lint + format check',
54
+ steps: ['kick typecheck', 'oxlint src/', 'oxfmt --check src/'],
55
+ aliases: ['verify'],
56
+ },
57
+ ],
58
+ })
@@ -0,0 +1,26 @@
1
+ import { Controller, Get, Autowired, type Ctx } from '@forinda/kickjs'
2
+ import { HelloService } from './hello.service'
3
+
4
+ // `Ctx<KickRoutes.HelloController['<method>']>` is generated by
5
+ // `kick typegen` (auto-run on `kick dev`). The first run after a fresh
6
+ // scaffold creates `.kickjs/types/routes.ts` so this file typechecks.
7
+ // See https://kickjs.app/guide/typegen.
8
+
9
+ @Controller()
10
+ export class HelloController {
11
+ @Autowired() private readonly helloService!: HelloService
12
+
13
+ // Return-value handlers: the runtime sends the returned payload as
14
+ // 200 json, and `kick typegen` infers the response type into
15
+ // `KickRoutes.Api` — which is what makes the typed client
16
+ // (@forinda/kickjs-client) end-to-end type-safe.
17
+ @Get('/')
18
+ index(_ctx: Ctx<KickRoutes.HelloController['index']>) {
19
+ return this.helloService.greet('World')
20
+ }
21
+
22
+ @Get('/health')
23
+ health(_ctx: Ctx<KickRoutes.HelloController['health']>) {
24
+ return this.helloService.healthCheck()
25
+ }
26
+ }
@@ -0,0 +1,21 @@
1
+ import { defineModule } from '@forinda/kickjs'
2
+ import { HelloController } from './hello.controller'
3
+
4
+ export const HelloModule = defineModule({
5
+ name: 'HelloModule',
6
+ build: () => ({
7
+ // `register(container)` is optional — only implement it when you need
8
+ // to bind a token to a concrete implementation, e.g.
9
+ // register(container) {
10
+ // container.registerFactory(USER_REPOSITORY, () => container.resolve(InMemoryUserRepository))
11
+ // }
12
+ // The HelloService uses @Service() so the decorator handles registration.
13
+
14
+ routes() {
15
+ return {
16
+ path: '/hello',
17
+ controller: HelloController,
18
+ }
19
+ },
20
+ }),
21
+ })
@@ -0,0 +1,12 @@
1
+ import { Service } from '@forinda/kickjs'
2
+
3
+ @Service()
4
+ export class HelloService {
5
+ greet(name: string) {
6
+ return { message: `Hello ${name} from KickJS!`, timestamp: new Date().toISOString() }
7
+ }
8
+
9
+ healthCheck() {
10
+ return { status: 'ok', uptime: process.uptime() }
11
+ }
12
+ }
@@ -0,0 +1,7 @@
1
+ import { defineModules } from '@forinda/kickjs'
2
+ import { HelloModule } from './hello/hello.module'
3
+
4
+ // Remove HelloModule and run: kick g module <name>
5
+ // `defineModules()` returns a chainable list — `kick g module` appends
6
+ // `.mount(NewModule())` to the chain on every generation.
7
+ export const modules = defineModules().mount(HelloModule())
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "types": ["node", "vite/client"],
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "sourceMap": true,
12
+ "declaration": true,
13
+ "experimentalDecorators": true,
14
+ "emitDecoratorMetadata": true,
15
+ "outDir": "dist",
16
+ "paths": {
17
+ "@/*": ["./src/*"]
18
+ }
19
+ },
20
+ "include": ["src", ".kickjs/types/**/*.d.ts", ".kickjs/types/**/*.ts"]
21
+ }
@@ -0,0 +1,31 @@
1
+ import { defineConfig } from 'vite'
2
+ import { fileURLToPath } from 'node:url'
3
+ import swc from 'unplugin-swc'
4
+ import { kickjsVitePlugin, envWatchPlugin } from '@forinda/kickjs-vite'
5
+
6
+ export default defineConfig({
7
+ oxc: false,
8
+ plugins: [
9
+ swc.vite(),
10
+ kickjsVitePlugin({ entry: 'src/index.ts' }),
11
+ // Watches .env files and triggers a full reload on change so the
12
+ // dev server picks up env tweaks without a manual restart.
13
+ envWatchPlugin(),
14
+ ],
15
+ // @kick:vite-option
16
+ resolve: {
17
+ alias: {
18
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
19
+ },
20
+ },
21
+ build: {
22
+ target: 'node20',
23
+ ssr: true,
24
+ outDir: 'dist',
25
+ sourcemap: true,
26
+ rollupOptions: {
27
+ input: fileURLToPath(new URL('./src/index.ts', import.meta.url)),
28
+ output: { format: 'esm' },
29
+ },
30
+ },
31
+ })
@@ -0,0 +1,18 @@
1
+ import { defineConfig, mergeConfig } from 'vitest/config'
2
+ import viteConfig from './vite.config.ts'
3
+
4
+ // A `vitest.config.ts` OVERRIDES `vite.config.ts` outright — vitest does not
5
+ // merge the two, and it never reads tsconfig `paths`. Restating settings here
6
+ // would mean the `@` alias lives in three files and drifts in two of them, so
7
+ // merge the real config instead: the alias, plugins, and ssr externals all come
8
+ // from one place.
9
+ export default mergeConfig(
10
+ viteConfig,
11
+ defineConfig({
12
+ test: {
13
+ globals: true,
14
+ environment: 'node',
15
+ include: ['src/**/*.test.ts'],
16
+ },
17
+ }),
18
+ )
@@ -0,0 +1,13 @@
1
+ {
2
+ "dependencies": ["@forinda/kickjs-devtools"],
3
+ "integrations": [
4
+ {
5
+ "import": {
6
+ "from": "@forinda/kickjs-devtools",
7
+ "names": ["DevToolsAdapter"]
8
+ },
9
+ "slot": "adapter",
10
+ "code": "DevToolsAdapter()"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "dependencies": ["@forinda/kickjs-queue", "bullmq", "ioredis"],
3
+ "builds": {
4
+ "msgpackr-extract": false
5
+ },
6
+ "integrations": [
7
+ {
8
+ "import": {
9
+ "from": "@forinda/kickjs-queue",
10
+ "names": ["QueueAdapter"]
11
+ },
12
+ "slot": "adapter",
13
+ "code": "// BullMQ over Redis. Nothing connects until a @Job class or a queue\n// is used, so the app boots without Redis running.\nQueueAdapter({\n redis: {\n host: process.env.REDIS_HOST ?? '127.0.0.1',\n port: Number(process.env.REDIS_PORT ?? 6379),\n },\n})"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,2 @@
1
+ REDIS_HOST=127.0.0.1
2
+ REDIS_PORT=6379
@@ -0,0 +1,2 @@
1
+ REDIS_HOST=127.0.0.1
2
+ REDIS_PORT=6379
@@ -0,0 +1,16 @@
1
+ {
2
+ "dependencies": ["@forinda/kickjs-swagger"],
3
+ "builds": {
4
+ "@scarf/scarf": true
5
+ },
6
+ "integrations": [
7
+ {
8
+ "import": {
9
+ "from": "@forinda/kickjs-swagger",
10
+ "names": ["SwaggerAdapter"]
11
+ },
12
+ "slot": "adapter",
13
+ "code": "SwaggerAdapter({ info: { title: '{{name}}', version: '{{version}}' } })"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "dependencies": ["@forinda/kickjs-ws", "ws"],
3
+ "integrations": [
4
+ {
5
+ "import": {
6
+ "from": "@forinda/kickjs-ws",
7
+ "names": ["WsAdapter"]
8
+ },
9
+ "slot": "adapter",
10
+ "code": "// WebSocket upgrades on /ws \u2014 see guide/websockets.\nWsAdapter({ path: '/ws' })"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,8 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ *.log
5
+ .DS_Store
6
+ # Platform build output — written by `kick build:netlify` / `kick build:vercel`.
7
+ .netlify/
8
+ .vercel/
@@ -0,0 +1,13 @@
1
+ [build]
2
+ command = "{{packageManager}} run build:netlify"
3
+ publish = "web/dist"
4
+
5
+ [build.environment]
6
+ NODE_VERSION = "22"
7
+
8
+ # Client-side routes fall back to the app shell. The function claims /api/*
9
+ # through its own `config.path`, so this rule never sees those requests.
10
+ [[redirects]]
11
+ from = "/*"
12
+ to = "/index.html"
13
+ status = 200
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://openapi.vercel.sh/vercel.json",
3
+ "framework": null,
4
+ "buildCommand": "{{packageManager}} run build:vercel"
5
+ }
@@ -0,0 +1,6 @@
1
+ [build]
2
+ command = "{{packageManager}} run build:netlify"
3
+ publish = "dist/public"
4
+
5
+ [build.environment]
6
+ NODE_VERSION = "22"
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://openapi.vercel.sh/vercel.json",
3
+ "framework": null,
4
+ "buildCommand": "{{packageManager}} run build:vercel"
5
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "dependencies": ["express"],
3
+ "devDependencies": ["@types/express"],
4
+ "integrations": [
5
+ {
6
+ "import": {
7
+ "from": "@forinda/kickjs",
8
+ "names": ["expressRuntime"]
9
+ },
10
+ "slot": "runtime",
11
+ "code": "runtime: expressRuntime()"
12
+ },
13
+ {
14
+ "import": {
15
+ "from": "express",
16
+ "default": "express"
17
+ },
18
+ "slot": "middleware",
19
+ "code": "// Express needs a body parser; Fastify and h3 parse bodies natively.\nexpress.json()"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "dependencies": ["fastify", "@fastify/middie", "serve-static"],
3
+ "integrations": [
4
+ {
5
+ "import": {
6
+ "from": "@forinda/kickjs/fastify",
7
+ "names": ["fastifyRuntime"]
8
+ },
9
+ "slot": "runtime",
10
+ "code": "runtime: fastifyRuntime()"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "dependencies": ["h3", "serve-static"],
3
+ "integrations": [
4
+ {
5
+ "import": {
6
+ "from": "@forinda/kickjs/h3",
7
+ "names": ["h3Runtime"]
8
+ },
9
+ "slot": "runtime",
10
+ "code": "runtime: h3Runtime()"
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "dependencies": ["valibot"]
3
+ }
@@ -0,0 +1,41 @@
1
+ import { loadEnvFromSchema } from '@forinda/kickjs/config'
2
+ import { fromValibot } from '@forinda/kickjs-schema/valibot'
3
+ import * as v from 'valibot'
4
+
5
+ /**
6
+ * Project environment schema (Valibot).
7
+ *
8
+ * `fromValibot` wraps the Valibot schema as a `KickSchema` so the
9
+ * env loader, validate middleware, and swagger spec generator all see
10
+ * the same shape. The default export is the contract `kick typegen`
11
+ * reads to populate `KickEnv` via `InferSchemaOutput<typeof _envSchema>`
12
+ * — that's what makes `@Value('FOO')` autocomplete and
13
+ * `process.env.FOO` typed.
14
+ *
15
+ * @example
16
+ * DATABASE_URL: v.pipe(v.string(), v.url()),
17
+ * JWT_SECRET: v.pipe(v.string(), v.minLength(32)),
18
+ * REDIS_URL: v.optional(v.pipe(v.string(), v.url())),
19
+ */
20
+ const envSchema = fromValibot(
21
+ v.object({
22
+ PORT: v.optional(v.pipe(v.string(), v.transform(Number)), '3000'),
23
+ NODE_ENV: v.optional(v.picklist(['development', 'production', 'test']), 'development'),
24
+ LOG_LEVEL: v.optional(v.string(), 'info'),
25
+ // DATABASE_URL: v.pipe(v.string(), v.url()),
26
+ }),
27
+ )
28
+
29
+ /**
30
+ * IMPORTANT — side effect: register the schema with kickjs's env cache
31
+ * **at module-load time**. `ConfigService` and `@Value()` both consume
32
+ * this cache, and they will fall back to the base schema (or undefined)
33
+ * if no extended schema has been registered before they're resolved.
34
+ *
35
+ * As long as `src/index.ts` imports this file (`import './config'`) at
36
+ * the top — before `bootstrap()` runs — every controller and service
37
+ * in the app sees the typed extended values.
38
+ */
39
+ export const env = loadEnvFromSchema(envSchema)
40
+
41
+ export default envSchema
@@ -0,0 +1,3 @@
1
+ {
2
+ "dependencies": ["yup"]
3
+ }