@grest-ts/create-starter 0.0.23 → 0.0.24

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/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { cpSync, readdirSync, renameSync, readFileSync, writeFileSync, statSync, existsSync } from "fs"
3
+ import { cpSync, readdirSync, renameSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, statSync, existsSync } from "fs"
4
4
  import { join, dirname } from "path"
5
5
  import { fileURLToPath } from "url"
6
6
  import { createInterface } from "readline/promises"
@@ -79,6 +79,19 @@ async function main() {
79
79
  }
80
80
  }
81
81
 
82
+ // 4. Fan out project-context.md to all AI tool locations, then remove the source file.
83
+ // Single source in template → CLAUDE.md, AGENTS.md, .cursor/rules/project.mdc in new project.
84
+ const projectContextSrc = join(targetDir, "project-context.md")
85
+ if (existsSync(projectContextSrc)) {
86
+ const body = readFileSync(projectContextSrc, "utf-8")
87
+ const mdcFrontmatter = `---\ndescription: grest-ts project context\nglobs: ["**/*.ts", "**/*.tsx"]\nalwaysApply: true\n---\n\n`
88
+ writeFileSync(join(targetDir, "CLAUDE.md"), body)
89
+ writeFileSync(join(targetDir, "AGENTS.md"), body)
90
+ mkdirSync(join(targetDir, ".cursor", "rules"), { recursive: true })
91
+ writeFileSync(join(targetDir, ".cursor", "rules", "project.mdc"), mdcFrontmatter + body)
92
+ unlinkSync(projectContextSrc)
93
+ }
94
+
82
95
  console.log(` Done! Next steps:`)
83
96
  console.log()
84
97
  console.log(` cd ${name}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grest-ts/create-starter",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Scaffold a new grest-ts project",
@@ -0,0 +1,25 @@
1
+ # Project context
2
+
3
+ This is a **grest-ts** project (npm workspaces monorepo).
4
+ Framework docs: https://github.com/grest-ts/grest-ts
5
+
6
+ ## Package layout
7
+
8
+ ```
9
+ api/ — shared API contracts (@newproject/api)
10
+ api/src/api/ ← contract definitions live here
11
+ server/ — backend implementation + integration tests
12
+ server/src/AppRuntime.ts ← runtime entry point (compose() wires everything)
13
+ server/src/services/ ← API implementations
14
+ server/test/integration/ ← integration tests
15
+ server/test/TestContext.ts ← extend GGTestContext here for auth helpers
16
+ client/ — frontend
17
+ ```
18
+
19
+ ## Key conventions
20
+
21
+ - Contracts defined in `api/` are imported by both `server/` and `client/`.
22
+ - All service wiring is in `AppRuntime.compose()` — no DI, plain constructors.
23
+ - Integration tests use `GGTest.startWorker(AppRuntime)` + `GGTestContext.apis()`.
24
+ - Run server: `cd server && npm run dev`
25
+ - Run tests: `cd server && npm test`
@@ -17,6 +17,7 @@
17
17
  "@grest-ts/runtime": "*",
18
18
  "@grest-ts/schema": "*",
19
19
  "@grest-ts/testkit": "*",
20
+ "@grest-ts/testkit-runtime": "*",
20
21
  "@grest-ts/testkit-vitest": "*",
21
22
  "@newproject/api": "*"
22
23
  },
@@ -4,6 +4,7 @@ import {GG_LOG} from "@grest-ts/logger"
4
4
  import {GGLoggerConsole} from "@grest-ts/logger-console"
5
5
  import {HelloApi} from "@newproject/api/api/HelloApi"
6
6
  import {HelloApiImpl} from "./services/HelloApiImpl"
7
+ import {GreetingService} from "./services/GreetingService"
7
8
 
8
9
  export class AppRuntime extends GGRuntime {
9
10
 
@@ -14,8 +15,10 @@ export class AppRuntime extends GGRuntime {
14
15
 
15
16
  const httpServer = new GGHttpServer()
16
17
 
18
+ const greetingService = new GreetingService()
19
+
17
20
  new GGHttp(httpServer)
18
- .http(HelloApi, new HelloApiImpl())
21
+ .http(HelloApi, new HelloApiImpl(greetingService))
19
22
  }
20
23
  }
21
24
 
@@ -0,0 +1,8 @@
1
+ import {mockable} from "@grest-ts/testkit-runtime"
2
+
3
+ @mockable
4
+ export class GreetingService {
5
+ async format(name: string): Promise<string> {
6
+ return `Hello, ${name}!`
7
+ }
8
+ }
@@ -1,8 +1,11 @@
1
1
  import type {HelloRequest, HelloResponse} from "@newproject/api/api/HelloApi"
2
+ import {GreetingService} from "./GreetingService"
2
3
 
3
4
  export class HelloApiImpl {
4
5
 
6
+ constructor(private readonly greetingService: GreetingService) {}
7
+
5
8
  public hello = async (input: HelloRequest): Promise<HelloResponse> => {
6
- return {message: `Hello, ${input.name}!`}
9
+ return {message: await this.greetingService.format(input.name)}
7
10
  }
8
11
  }
@@ -1,6 +1,7 @@
1
- import {GGTest} from "@grest-ts/testkit"
1
+ import {GGTest, mockOf} from "@grest-ts/testkit"
2
2
  import {AppRuntime} from "../../src/AppRuntime"
3
3
  import {HelloApi} from "@newproject/api/api/HelloApi"
4
+ import {GreetingService} from "../../src/services/GreetingService"
4
5
  import {TestContext} from "../TestContext"
5
6
 
6
7
  describe("Hello API", () => {
@@ -19,4 +20,13 @@ describe("Hello API", () => {
19
20
  await ctx.hello.hello({name: "Alice"})
20
21
  .toMatchObject({message: "Hello, Alice!"})
21
22
  })
23
+
24
+ test("hello uses GreetingService (mockable demo)", async () => {
25
+ await ctx.hello.hello({name: "World"})
26
+ .with(mockOf(GreetingService).format
27
+ .toEqual({name: "World"})
28
+ .andReturn("Mocked!")
29
+ )
30
+ .toMatchObject({message: "Mocked!"})
31
+ })
22
32
  })