@lyku/lockstep-handles-ts 1.0.0 → 1.3.1
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/LLMs.md +88 -0
- package/README.md +130 -0
- package/package.json +2 -1
package/LLMs.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# @lyku/lockstep-handles-ts — LLM Reference
|
|
2
|
+
|
|
3
|
+
This document is a mechanical reference for `@lyku/lockstep-handles-ts`, the TypeScript handler factory generator in the lockstep toolkit.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Generates typed handler wrappers from `TsonHandlerModel` API definitions. Each generated handler factory:
|
|
8
|
+
|
|
9
|
+
1. Embeds a runtime request validator (built from the model's `request` schema)
|
|
10
|
+
2. Attaches the model definition for framework consumption
|
|
11
|
+
3. Provides full TypeScript types for request, response, and context
|
|
12
|
+
|
|
13
|
+
## API
|
|
14
|
+
|
|
15
|
+
### `generateHandles(options: GenerateHandlesOptions): Promise<void>`
|
|
16
|
+
|
|
17
|
+
Single entry point. Generates `.js` and `.d.ts` files for every handler model in the input.
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
interface GenerateHandlesOptions {
|
|
21
|
+
models: Record<string, unknown>; // Endpoint models (auto-filtered)
|
|
22
|
+
outputDir: string; // Output directory
|
|
23
|
+
modelsPackage: string; // e.g. '@myapp/api-models'
|
|
24
|
+
typesPackage: string; // e.g. '@myapp/api-types'
|
|
25
|
+
contextPackage?: string; // default: '@lyku/lockstep-core/contexts'
|
|
26
|
+
typesName?: string; // default: 'ApiTypes'
|
|
27
|
+
clean?: boolean; // default: true
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Generated file structure
|
|
32
|
+
|
|
33
|
+
For each handler model entry (e.g. `createUser`):
|
|
34
|
+
|
|
35
|
+
### `createUser.js`
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import { createUser } from '@myapp/api-models';
|
|
39
|
+
import { isObject } from '@lyku/lockstep-core'; // only if validator uses it
|
|
40
|
+
|
|
41
|
+
export const handleCreateUser = (handler) => ({
|
|
42
|
+
execute: handler, // 'execute' for HTTP, 'onOpen' for WebSocket
|
|
43
|
+
validator: { validate, validateOrThrow, isValid },
|
|
44
|
+
model: {
|
|
45
|
+
/* serialized TsonHandlerModel */
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### `createUser.d.ts`
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { createUser } from '@myapp/api-models';
|
|
54
|
+
import type { MyApiTypes } from '@myapp/api-types';
|
|
55
|
+
import type { CreateUserRequest, CreateUserResponse } from '@myapp/api-types';
|
|
56
|
+
import type { SecureHttpContext } from '@lyku/lockstep-core/contexts';
|
|
57
|
+
|
|
58
|
+
export declare const handleCreateUser: (handler: (request: CreateUserRequest, context: SecureHttpContext<typeof createUser>) => CreateUserResponse | Promise<CreateUserResponse>) => {
|
|
59
|
+
/* ... */
|
|
60
|
+
};
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Context type selection
|
|
64
|
+
|
|
65
|
+
| Protocol | Authenticated | Context Type |
|
|
66
|
+
| --------- | ------------- | -------------------------- |
|
|
67
|
+
| HTTP | true | `SecureHttpContext` |
|
|
68
|
+
| HTTP | false | `MaybeSecureHttpContext` |
|
|
69
|
+
| WebSocket | true | `SecureSocketContext` |
|
|
70
|
+
| WebSocket | false | `MaybeSecureSocketContext` |
|
|
71
|
+
|
|
72
|
+
HTTP vs WebSocket is determined by `model.stream`. Authentication by `model.authenticated`.
|
|
73
|
+
|
|
74
|
+
## Key behaviors
|
|
75
|
+
|
|
76
|
+
- **Filtering**: `filterHandlerModels()` from lockstep-core removes non-handler entries from the models record before generation
|
|
77
|
+
- **Validator embedding**: Validators are serialized as inline JavaScript strings (not imports) so handlers are self-contained
|
|
78
|
+
- **Formatting**: All output is formatted with prettier via `formatCode()` from lockstep-core
|
|
79
|
+
- **Naming convention**: endpoint `foo` → factory `handleFoo`, types `FooRequest`/`FooResponse`
|
|
80
|
+
- **WebSocket tweakRequest**: If `model.stream.tweakRequest` exists, a `tweakValidator` is also generated
|
|
81
|
+
- **Index files**: `index.js` uses `.js` extensions in re-exports; `index.d.ts` uses bare specifiers
|
|
82
|
+
|
|
83
|
+
## Dependencies
|
|
84
|
+
|
|
85
|
+
| Package | Used for |
|
|
86
|
+
| -------------------------------- | -------------------------------------------- |
|
|
87
|
+
| `@lyku/lockstep-core` | `buildValidator`, `stringifyBON`, `isObject` |
|
|
88
|
+
| `@lyku/lockstep-core/generators` | `formatCode`, `filterHandlerModels` |
|
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# @lyku/lockstep-handles-ts
|
|
2
|
+
|
|
3
|
+
Generate typed handler factories from `TsonHandlerModel` API definitions. Part of the [lockstep](https://github.com/muzzin/lyku) schema toolkit.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Takes your API endpoint models and generates:
|
|
8
|
+
|
|
9
|
+
- **Handler factories** (`handleCreateUser`, `handleGetPost`, etc.) — typed wrappers that enforce request/response types
|
|
10
|
+
- **Runtime validators** — built from the schema, embedded in each handler
|
|
11
|
+
- **TypeScript declarations** — `.d.ts` files with full context types (auth, WebSocket, HTTP)
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { generateHandles } from '@lyku/lockstep-handles-ts';
|
|
17
|
+
import * as models from '@myapp/api-models';
|
|
18
|
+
|
|
19
|
+
await generateHandles({
|
|
20
|
+
models,
|
|
21
|
+
outputDir: 'dist/libs/handles/src',
|
|
22
|
+
modelsPackage: '@myapp/api-models',
|
|
23
|
+
typesPackage: '@myapp/api-types',
|
|
24
|
+
typesName: 'MyApiTypes',
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Options
|
|
29
|
+
|
|
30
|
+
| Option | Type | Default | Description |
|
|
31
|
+
| ---------------- | --------- | -------------------------------- | -------------------------------------------------- |
|
|
32
|
+
| `models` | `Record` | required | Endpoint name to model map (non-handlers filtered) |
|
|
33
|
+
| `outputDir` | `string` | required | Where to write generated files |
|
|
34
|
+
| `modelsPackage` | `string` | required | Import path for API model definitions |
|
|
35
|
+
| `typesPackage` | `string` | required | Import path for generated request/response types |
|
|
36
|
+
| `contextPackage` | `string` | `'@lyku/lockstep-core/contexts'` | Import path for handler context types |
|
|
37
|
+
| `typesName` | `string` | `'ApiTypes'` | Name of the aggregate types map |
|
|
38
|
+
| `clean` | `boolean` | `true` | Clean output directory before generating |
|
|
39
|
+
|
|
40
|
+
## Generated output
|
|
41
|
+
|
|
42
|
+
For an endpoint `createUser`:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
outputDir/
|
|
46
|
+
createUser.js # Handler factory with embedded validator
|
|
47
|
+
createUser.d.ts # TypeScript declaration
|
|
48
|
+
index.js # Re-exports all handlers
|
|
49
|
+
index.d.ts # Re-exports all types
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The generated handler factory:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { handleCreateUser } from '@myapp/handles';
|
|
56
|
+
|
|
57
|
+
export const createUser = handleCreateUser(async (request, context) => {
|
|
58
|
+
// request is typed as CreateUserRequest
|
|
59
|
+
// context includes auth, session, etc.
|
|
60
|
+
return { id: newUser.id };
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Where it fits
|
|
65
|
+
|
|
66
|
+
<!-- Generated from libs/lockstep-core/diagrams/pipeline.mmd — do not edit manually -->
|
|
67
|
+
|
|
68
|
+
```mermaid
|
|
69
|
+
graph TD
|
|
70
|
+
input-tables["Table Schemas<br/><small>PostgresRecordModel</small>"]
|
|
71
|
+
input-api["API Definitions<br/><small>TsonHandlerModel</small>"]
|
|
72
|
+
|
|
73
|
+
core-jsonmodels["generateJsonModels"]
|
|
74
|
+
core-dbtypes["generateDbTypes"]
|
|
75
|
+
core-apitypes["generateApiTypes"]
|
|
76
|
+
core-validators["buildValidator"]
|
|
77
|
+
|
|
78
|
+
handles-gen["generateHandles"]
|
|
79
|
+
|
|
80
|
+
client-gen["generateTsClient"]
|
|
81
|
+
|
|
82
|
+
pg-drift["detectDrift"]
|
|
83
|
+
pg-migrate["generateMigration"]
|
|
84
|
+
|
|
85
|
+
output-jsonschemas["JSON Schemas +<br/>TypeScript Types"]
|
|
86
|
+
output-kysely["Kysely Database<br/>Interface"]
|
|
87
|
+
output-reqres["Request / Response<br/>TypeScript Types"]
|
|
88
|
+
output-handlers["Handler Factories<br/>+ Validators"]
|
|
89
|
+
output-client["Type-safe<br/>HTTP Client"]
|
|
90
|
+
output-sql["SQL Migrations"]
|
|
91
|
+
|
|
92
|
+
input-tables --> core-jsonmodels
|
|
93
|
+
core-jsonmodels --> output-jsonschemas
|
|
94
|
+
output-jsonschemas --> core-dbtypes
|
|
95
|
+
core-dbtypes --> output-kysely
|
|
96
|
+
|
|
97
|
+
input-api --> core-apitypes
|
|
98
|
+
core-apitypes --> output-reqres
|
|
99
|
+
input-api --> core-validators
|
|
100
|
+
|
|
101
|
+
output-reqres --> handles-gen
|
|
102
|
+
input-api --> handles-gen
|
|
103
|
+
core-validators -.-> handles-gen
|
|
104
|
+
handles-gen --> output-handlers
|
|
105
|
+
|
|
106
|
+
output-reqres --> client-gen
|
|
107
|
+
input-api --> client-gen
|
|
108
|
+
client-gen --> output-client
|
|
109
|
+
|
|
110
|
+
input-tables --> pg-drift
|
|
111
|
+
pg-drift --> pg-migrate
|
|
112
|
+
pg-migrate --> output-sql
|
|
113
|
+
|
|
114
|
+
classDef highlight fill:#4f46e5,stroke:#3730a3,color:#fff,stroke-width:2px
|
|
115
|
+
classDef dimmed fill:#f1f5f9,stroke:#cbd5e1,color:#94a3b8,stroke-width:1px
|
|
116
|
+
classDef inputNode fill:#fef3c7,stroke:#f59e0b,color:#92400e,stroke-width:1px
|
|
117
|
+
classDef outputNode fill:#d1fae5,stroke:#10b981,color:#065f46,stroke-width:1px
|
|
118
|
+
classDef ownedOutput fill:#a5b4fc,stroke:#4f46e5,color:#1e1b4b,stroke-width:2px
|
|
119
|
+
classDef ownedInput fill:#fde68a,stroke:#4f46e5,color:#1e1b4b,stroke-width:2px
|
|
120
|
+
class handles-gen highlight
|
|
121
|
+
class core-jsonmodels,core-dbtypes,core-apitypes,core-validators,client-gen,pg-drift,pg-migrate dimmed
|
|
122
|
+
class input-tables inputNode
|
|
123
|
+
class output-jsonschemas,output-kysely,output-reqres,output-client,output-sql outputNode
|
|
124
|
+
class input-api ownedInput
|
|
125
|
+
class output-handlers ownedOutput
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Requirements
|
|
129
|
+
|
|
130
|
+
Peer dependency on `@lyku/lockstep-core` (provides `buildValidator`, `stringifyBON`, `formatCode`, and `filterHandlerModels`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lyku/lockstep-handles-ts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Generate typed handler factories from TsonHandlerModel API definitions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"author": "Lyku",
|
|
24
24
|
"license": "GPL-3.0",
|
|
25
25
|
"devDependencies": {
|
|
26
|
+
"@lyku/lockstep-core": "1.3.1",
|
|
26
27
|
"typescript": "^5.0.0"
|
|
27
28
|
},
|
|
28
29
|
"module": "./src/index.js"
|