@terreno/api 0.0.11 → 0.0.12
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/CLAUDE.md +107 -0
- package/biome.jsonc +1 -1
- package/bunfig.toml +3 -2
- package/dist/api.arrayOperations.test.d.ts +1 -0
- package/dist/api.arrayOperations.test.js +868 -0
- package/dist/api.d.ts +3 -14
- package/dist/api.errors.test.d.ts +1 -0
- package/dist/api.errors.test.js +175 -0
- package/dist/api.hooks.test.d.ts +1 -0
- package/dist/api.hooks.test.js +891 -0
- package/dist/api.js +44 -68
- package/dist/api.query.test.d.ts +1 -0
- package/dist/api.query.test.js +805 -0
- package/dist/api.test.js +691 -1678
- package/dist/auth.test.js +135 -0
- package/dist/expressServer.test.d.ts +1 -0
- package/dist/expressServer.test.js +669 -0
- package/dist/notifiers/slackNotifier.d.ts +2 -1
- package/dist/notifiers/slackNotifier.js +20 -13
- package/dist/permissions.d.ts +1 -1
- package/dist/permissions.js +17 -25
- package/dist/permissions.test.js +57 -0
- package/dist/populate.test.js +52 -0
- package/dist/tests.d.ts +9 -27
- package/dist/utils.test.js +235 -7
- package/package.json +3 -2
- package/src/api.arrayOperations.test.ts +690 -0
- package/src/api.errors.test.ts +156 -0
- package/src/api.hooks.test.ts +704 -0
- package/src/api.query.test.ts +538 -0
- package/src/api.test.ts +510 -1301
- package/src/api.ts +19 -61
- package/src/auth.test.ts +72 -0
- package/src/expressServer.test.ts +579 -0
- package/src/notifiers/slackNotifier.ts +28 -17
- package/src/permissions.test.ts +70 -1
- package/src/permissions.ts +4 -14
- package/src/populate.test.ts +58 -0
- package/src/utils.test.ts +214 -9
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @terreno/api
|
|
2
|
+
|
|
3
|
+
REST API framework built on Express/Mongoose, styled after Django REST Framework.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun run compile # Compile TypeScript
|
|
9
|
+
bun run dev # Watch mode
|
|
10
|
+
bun run test # Run tests
|
|
11
|
+
bun run lint # Lint code
|
|
12
|
+
bun run lint:fix # Fix lint issues
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Architecture
|
|
16
|
+
|
|
17
|
+
### modelRouter
|
|
18
|
+
|
|
19
|
+
Automatically creates RESTful CRUD APIs for Mongoose models with built-in permissions, population, filtering, and lifecycle hooks.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import {modelRouter, modelRouterOptions, Permissions} from "@terreno/api";
|
|
23
|
+
|
|
24
|
+
const router = modelRouter(YourModel, {
|
|
25
|
+
permissions: {
|
|
26
|
+
list: [Permissions.IsAuthenticated],
|
|
27
|
+
create: [Permissions.IsAuthenticated],
|
|
28
|
+
read: [Permissions.IsOwner],
|
|
29
|
+
update: [Permissions.IsOwner],
|
|
30
|
+
delete: [], // Disabled
|
|
31
|
+
},
|
|
32
|
+
sort: "-created",
|
|
33
|
+
queryFields: ["_id", "type", "name"],
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Custom Routes
|
|
38
|
+
|
|
39
|
+
For non-CRUD endpoints, use the OpenAPI builder:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import {asyncHandler, authenticateMiddleware, createOpenApiBuilder} from "@terreno/api";
|
|
43
|
+
|
|
44
|
+
router.get("/yourRoute/:id", [
|
|
45
|
+
authenticateMiddleware(),
|
|
46
|
+
createOpenApiBuilder(options)
|
|
47
|
+
.withTags(["yourTag"])
|
|
48
|
+
.withSummary("Brief summary")
|
|
49
|
+
.withPathParameter("id", {type: "string"})
|
|
50
|
+
.withResponse(200, {data: {type: "object"}})
|
|
51
|
+
.build(),
|
|
52
|
+
], asyncHandler(async (req, res) => {
|
|
53
|
+
return res.json({data: result});
|
|
54
|
+
}));
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Conventions
|
|
58
|
+
|
|
59
|
+
### Error Handling
|
|
60
|
+
- Throw `APIError` with appropriate status codes: `throw new APIError({status: 400, title: "Message"})`
|
|
61
|
+
- Services should throw user-friendly errors
|
|
62
|
+
|
|
63
|
+
### Mongoose
|
|
64
|
+
- Do not use `Model.findOne` - use `Model.findExactlyOne` or `Model.findOneOrThrow`
|
|
65
|
+
- Define statics/methods by direct assignment: `schema.methods = {bar() {}}`
|
|
66
|
+
- All model types live in `src/modelInterfaces.ts`
|
|
67
|
+
|
|
68
|
+
### User Type Casting
|
|
69
|
+
- In API routes: `req.user` is `UserDocument | undefined`
|
|
70
|
+
- In @terreno/api callbacks: cast with `const user = u as unknown as UserDocument`
|
|
71
|
+
- Never use `as any as UserDocument`
|
|
72
|
+
|
|
73
|
+
### Logging
|
|
74
|
+
- Use `logger.info/warn/error/debug` for permanent logs (not `console.log`)
|
|
75
|
+
|
|
76
|
+
### Testing
|
|
77
|
+
- Use bun test with expect for testing
|
|
78
|
+
- Use existing manual mocks from `src/__mocks__/`
|
|
79
|
+
- Never mock @terreno/api or models
|
|
80
|
+
|
|
81
|
+
## Model Type Generation
|
|
82
|
+
|
|
83
|
+
When creating/modifying Mongoose models, update `src/modelInterfaces.ts`:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
export type YourModelMethods = {
|
|
87
|
+
customMethod: (this: YourModelDocument, param: string) => Promise<void>;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type YourModelStatics = DefaultStatics<YourModelDocument> & {
|
|
91
|
+
customStatic: (this: YourModelModel, param: string) => Promise<YourModelDocument>;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type YourModelModel = DefaultModel<YourModelDocument> & YourModelStatics;
|
|
95
|
+
export type YourModelSchema = mongoose.Schema<YourModelDocument, YourModelModel, YourModelMethods>;
|
|
96
|
+
export type YourModelDocument = DefaultDoc & YourModelMethods & {
|
|
97
|
+
fieldName: string;
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## SDK Generation
|
|
102
|
+
|
|
103
|
+
After modifying routes, regenerate the SDK:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
bun run sdk
|
|
107
|
+
```
|
package/biome.jsonc
CHANGED
package/bunfig.toml
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
[test]
|
|
2
2
|
preload = ["./src/tests/bunSetup.ts"]
|
|
3
3
|
root = "./src"
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
coverage = true
|
|
5
|
+
coverageExclude = ["dist/**", "**/*.test.ts", "**/tests/**"]
|
|
6
|
+
coverageThreshold = { line = 80, function = 80 }
|
|
6
7
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|