@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 +14 -1
- package/package.json +1 -1
- package/template/project-context.md +25 -0
- package/template/server/package.json +1 -0
- package/template/server/src/AppRuntime.ts +4 -1
- package/template/server/src/services/GreetingService.ts +8 -0
- package/template/server/src/services/HelloApiImpl.ts +4 -1
- package/template/server/test/integration/hello.test.ts +11 -1
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
|
@@ -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`
|
|
@@ -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
|
|
|
@@ -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:
|
|
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
|
})
|