@celerity-sdk/cli 0.3.1 → 0.4.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.
- package/README.md +106 -5
- package/dist/extract/cli.cjs +369 -47
- package/dist/extract/cli.cjs.map +1 -1
- package/dist/extract/cli.js +370 -48
- package/dist/extract/cli.js.map +1 -1
- package/dist/index.cjs +369 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +370 -48
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/schemas/handler-manifest.v1.schema.json +56 -11
package/README.md
CHANGED
|
@@ -24,6 +24,23 @@ The Go-based Celerity CLI invokes this tool during the build phase to merge code
|
|
|
24
24
|
2. **Serialization** (`serializeManifest`) - converts scanned metadata into a structured manifest with handler entries, annotations, and a dependency graph.
|
|
25
25
|
3. **Validation** (`validateScannedDependencies`) - checks that all provider dependencies are resolvable, reporting diagnostics for missing tokens.
|
|
26
26
|
|
|
27
|
+
## Supported Handler Types
|
|
28
|
+
|
|
29
|
+
The extraction tool produces manifest entries for both **class-based** (decorator-driven) and **function-based** (blueprint-driven) handlers across all handler types:
|
|
30
|
+
|
|
31
|
+
| Handler Type | Class Decorator | Function Type | Description |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| HTTP | `@Get`, `@Post`, `@Put`, `@Patch`, `@Delete` | `"http"` | REST API route handlers |
|
|
34
|
+
| WebSocket | `@OnConnect`, `@OnDisconnect`, `@OnMessage` | `"websocket"` | WebSocket event handlers |
|
|
35
|
+
| Consumer | `@ConsumerHandler` | `"consumer"` | Queue/topic message consumers |
|
|
36
|
+
| Schedule | `@ScheduleHandler` | `"schedule"` | Cron/rate scheduled handlers |
|
|
37
|
+
| Custom | `@Invoke` | `"custom"` | Direct invocation handlers |
|
|
38
|
+
| Guard | `@Guard` (class) or `defineGuard` (function) | — | Custom guard implementations |
|
|
39
|
+
|
|
40
|
+
### Cross-Cutting Decorators
|
|
41
|
+
|
|
42
|
+
`@ScheduleHandler` and `@Invoke` are cross-cutting — they can be applied to methods on any controller type (HTTP, WebSocket, or Consumer), producing additional manifest entries alongside the primary handler entry.
|
|
43
|
+
|
|
27
44
|
## Manifest Structure
|
|
28
45
|
|
|
29
46
|
The output conforms to `handler-manifest.v1.schema.json`:
|
|
@@ -51,24 +68,108 @@ The output conforms to `handler-manifest.v1.schema.json`:
|
|
|
51
68
|
}
|
|
52
69
|
}
|
|
53
70
|
],
|
|
54
|
-
"functionHandlers": [
|
|
71
|
+
"functionHandlers": [
|
|
72
|
+
{
|
|
73
|
+
"resourceName": "processOrder",
|
|
74
|
+
"exportName": "processOrder",
|
|
75
|
+
"handlerType": "consumer",
|
|
76
|
+
"sourceFile": "/project/src/app.module.ts",
|
|
77
|
+
"annotations": {
|
|
78
|
+
"celerity.handler.consumer": true,
|
|
79
|
+
"celerity.handler.consumer.route": "orders.*"
|
|
80
|
+
},
|
|
81
|
+
"spec": {
|
|
82
|
+
"handlerName": "processOrder",
|
|
83
|
+
"codeLocation": "./src",
|
|
84
|
+
"handler": "app.module.processOrder"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"guardHandlers": [
|
|
89
|
+
{
|
|
90
|
+
"resourceName": "rateLimiter_check",
|
|
91
|
+
"guardName": "rateLimiter",
|
|
92
|
+
"guardType": "class",
|
|
93
|
+
"className": "RateLimiter",
|
|
94
|
+
"sourceFile": "/project/src/app.module.ts",
|
|
95
|
+
"annotations": {
|
|
96
|
+
"celerity.handler.guard.custom": "rateLimiter"
|
|
97
|
+
},
|
|
98
|
+
"spec": {
|
|
99
|
+
"handlerName": "RateLimiter-check",
|
|
100
|
+
"codeLocation": "./src",
|
|
101
|
+
"handler": "app.module.RateLimiter.check"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
],
|
|
55
105
|
"dependencyGraph": {
|
|
56
|
-
"nodes": [
|
|
106
|
+
"nodes": [
|
|
107
|
+
{
|
|
108
|
+
"token": "OrderService",
|
|
109
|
+
"tokenType": "class",
|
|
110
|
+
"providerType": "class",
|
|
111
|
+
"dependencies": ["celerity:datastore:default"]
|
|
112
|
+
}
|
|
113
|
+
]
|
|
57
114
|
}
|
|
58
115
|
}
|
|
59
116
|
```
|
|
60
117
|
|
|
61
118
|
## Annotation Types
|
|
62
119
|
|
|
120
|
+
### HTTP
|
|
121
|
+
|
|
63
122
|
| Annotation | Source |
|
|
64
123
|
|---|---|
|
|
65
|
-
| `celerity.handler.http` | `@Get`, `@Post`,
|
|
124
|
+
| `celerity.handler.http` | `@Get`, `@Post`, `@Put`, `@Patch`, `@Delete` |
|
|
66
125
|
| `celerity.handler.http.method` | HTTP method from decorator |
|
|
67
|
-
| `celerity.handler.http.path` | Full path (prefix + route) |
|
|
126
|
+
| `celerity.handler.http.path` | Full path (controller prefix + route) |
|
|
127
|
+
|
|
128
|
+
### WebSocket
|
|
129
|
+
|
|
130
|
+
| Annotation | Source |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `celerity.handler.websocket` | `@OnConnect`, `@OnDisconnect`, `@OnMessage` |
|
|
133
|
+
| `celerity.handler.websocket.route` | WebSocket route key |
|
|
134
|
+
| `celerity.handler.websocket.eventType` | `connect`, `disconnect`, or `message` |
|
|
135
|
+
|
|
136
|
+
### Consumer
|
|
137
|
+
|
|
138
|
+
| Annotation | Source |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `celerity.handler.consumer` | `@ConsumerHandler` |
|
|
141
|
+
| `celerity.handler.consumer.sourceId` | Source ID from `@Consumer` controller |
|
|
142
|
+
| `celerity.handler.consumer.route` | Message routing pattern |
|
|
143
|
+
|
|
144
|
+
### Schedule
|
|
145
|
+
|
|
146
|
+
| Annotation | Source |
|
|
147
|
+
|---|---|
|
|
148
|
+
| `celerity.handler.schedule` | `@ScheduleHandler` |
|
|
149
|
+
| `celerity.handler.schedule.scheduleId` | Schedule identifier |
|
|
150
|
+
| `celerity.handler.schedule.expression` | Cron or rate expression |
|
|
151
|
+
|
|
152
|
+
### Custom (Invoke)
|
|
153
|
+
|
|
154
|
+
| Annotation | Source |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `celerity.handler.custom` | `@Invoke` |
|
|
157
|
+
| `celerity.handler.custom.name` | Invocation name |
|
|
158
|
+
|
|
159
|
+
### Guards
|
|
160
|
+
|
|
161
|
+
| Annotation | Source |
|
|
162
|
+
|---|---|
|
|
68
163
|
| `celerity.handler.guard.protectedBy` | `@ProtectedBy(...)` |
|
|
69
|
-
| `celerity.handler.guard.custom` | `@Guard(name)` |
|
|
164
|
+
| `celerity.handler.guard.custom` | `@Guard(name)` or `defineGuard` |
|
|
70
165
|
| `celerity.handler.public` | `@Public()` |
|
|
166
|
+
|
|
167
|
+
### Shared
|
|
168
|
+
|
|
169
|
+
| Annotation | Source |
|
|
170
|
+
|---|---|
|
|
71
171
|
| `celerity.handler.metadata.*` | `@SetMetadata(key, value)`, `@Action(name)` |
|
|
172
|
+
| `celerity.handler.resource.ref` | `@Bucket`, `@Queue`, `@Topic`, etc. |
|
|
72
173
|
|
|
73
174
|
## Part of the Celerity Framework
|
|
74
175
|
|
package/dist/extract/cli.cjs
CHANGED
|
@@ -57,10 +57,12 @@ function buildScannedModule(rootModule) {
|
|
|
57
57
|
const graph = (0, import_core.buildModuleGraph)(rootModule);
|
|
58
58
|
const controllerClasses = [];
|
|
59
59
|
const functionHandlers = [];
|
|
60
|
+
const guardClasses = [];
|
|
61
|
+
const functionGuards = [];
|
|
60
62
|
const providers = [];
|
|
61
63
|
const seenTokens = /* @__PURE__ */ new Set();
|
|
62
64
|
for (const [moduleClass, node] of graph) {
|
|
63
|
-
debug("scan: module %s \u2014 %d providers, %d controllers", moduleClass.name, node.providers.length, node.controllers.length);
|
|
65
|
+
debug("scan: module %s \u2014 %d providers, %d controllers, %d guards", moduleClass.name, node.providers.length, node.controllers.length, node.guards.length);
|
|
64
66
|
for (const provider of node.providers) {
|
|
65
67
|
const scanned = scanProvider(provider, seenTokens);
|
|
66
68
|
if (scanned) providers.push(scanned);
|
|
@@ -76,11 +78,28 @@ function buildScannedModule(rootModule) {
|
|
|
76
78
|
});
|
|
77
79
|
}
|
|
78
80
|
}
|
|
81
|
+
for (const guard of node.guards) {
|
|
82
|
+
if (typeof guard === "function") {
|
|
83
|
+
guardClasses.push(guard);
|
|
84
|
+
if (!seenTokens.has(guard)) {
|
|
85
|
+
seenTokens.add(guard);
|
|
86
|
+
providers.push({
|
|
87
|
+
token: guard,
|
|
88
|
+
providerType: "class",
|
|
89
|
+
dependencies: (0, import_core.getClassDependencyTokens)(guard)
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
functionGuards.push(guard);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
79
96
|
functionHandlers.push(...node.functionHandlers);
|
|
80
97
|
}
|
|
81
98
|
return {
|
|
82
99
|
controllerClasses,
|
|
83
100
|
functionHandlers,
|
|
101
|
+
guardClasses,
|
|
102
|
+
functionGuards,
|
|
84
103
|
providers
|
|
85
104
|
};
|
|
86
105
|
}
|
|
@@ -165,8 +184,9 @@ __name(deriveCodeLocation, "deriveCodeLocation");
|
|
|
165
184
|
function serializeManifest(scanned, sourceFile, options) {
|
|
166
185
|
const handlers = [];
|
|
167
186
|
const functionHandlers = [];
|
|
187
|
+
const guardHandlers = [];
|
|
168
188
|
for (const controllerClass of scanned.controllerClasses) {
|
|
169
|
-
const entries =
|
|
189
|
+
const entries = serializeClassHandlers(controllerClass, sourceFile, options);
|
|
170
190
|
handlers.push(...entries);
|
|
171
191
|
}
|
|
172
192
|
for (const fnHandler of scanned.functionHandlers) {
|
|
@@ -175,40 +195,76 @@ function serializeManifest(scanned, sourceFile, options) {
|
|
|
175
195
|
functionHandlers.push(entry);
|
|
176
196
|
}
|
|
177
197
|
}
|
|
198
|
+
for (const guardClass of scanned.guardClasses) {
|
|
199
|
+
const entry = serializeClassGuard(guardClass, sourceFile, options);
|
|
200
|
+
if (entry) {
|
|
201
|
+
guardHandlers.push(entry);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const fnGuard of scanned.functionGuards) {
|
|
205
|
+
const entry = serializeFunctionGuard(fnGuard, sourceFile, options);
|
|
206
|
+
if (entry) {
|
|
207
|
+
guardHandlers.push(entry);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
178
210
|
return {
|
|
179
211
|
version: "1.0.0",
|
|
180
212
|
handlers,
|
|
181
213
|
functionHandlers,
|
|
214
|
+
guardHandlers,
|
|
182
215
|
dependencyGraph: serializeDependencyGraph(scanned)
|
|
183
216
|
};
|
|
184
217
|
}
|
|
185
218
|
__name(serializeManifest, "serializeManifest");
|
|
186
|
-
function
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
219
|
+
function extractControllerMeta(controllerClass) {
|
|
220
|
+
const httpMeta = Reflect.getOwnMetadata(import_core2.CONTROLLER_METADATA, controllerClass);
|
|
221
|
+
if (httpMeta) {
|
|
222
|
+
return {
|
|
223
|
+
controllerType: "http",
|
|
224
|
+
prefix: httpMeta.prefix ?? "",
|
|
225
|
+
...extractSharedClassMeta(controllerClass)
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
const isWebSocket = Reflect.getOwnMetadata(import_core2.WEBSOCKET_CONTROLLER_METADATA, controllerClass);
|
|
229
|
+
if (isWebSocket) {
|
|
230
|
+
return {
|
|
231
|
+
controllerType: "websocket",
|
|
232
|
+
prefix: "",
|
|
233
|
+
...extractSharedClassMeta(controllerClass)
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
const consumerMeta = Reflect.getOwnMetadata(import_core2.CONSUMER_METADATA, controllerClass);
|
|
237
|
+
if (consumerMeta) {
|
|
238
|
+
return {
|
|
239
|
+
controllerType: "consumer",
|
|
240
|
+
prefix: "",
|
|
241
|
+
sourceId: consumerMeta.sourceId,
|
|
242
|
+
...extractSharedClassMeta(controllerClass)
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
__name(extractControllerMeta, "extractControllerMeta");
|
|
248
|
+
function extractSharedClassMeta(controllerClass) {
|
|
189
249
|
return {
|
|
190
|
-
prefix: controllerMeta.prefix ?? "",
|
|
191
250
|
protectedBy: Reflect.getOwnMetadata(import_core2.GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [],
|
|
192
251
|
customGuardName: Reflect.getOwnMetadata(import_core2.GUARD_CUSTOM_METADATA, controllerClass),
|
|
193
|
-
customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, controllerClass) ?? {}
|
|
252
|
+
customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, controllerClass) ?? {},
|
|
253
|
+
resourceRefs: Reflect.getOwnMetadata(import_core2.USE_RESOURCE_METADATA, controllerClass) ?? []
|
|
194
254
|
};
|
|
195
255
|
}
|
|
196
|
-
__name(
|
|
197
|
-
function
|
|
198
|
-
const annotations = {};
|
|
199
|
-
annotations["celerity.handler.http"] = true;
|
|
200
|
-
annotations["celerity.handler.http.method"] = httpMethod;
|
|
201
|
-
annotations["celerity.handler.http.path"] = fullPath;
|
|
256
|
+
__name(extractSharedClassMeta, "extractSharedClassMeta");
|
|
257
|
+
function appendSharedAnnotations(annotations, meta, prototype, methodName) {
|
|
202
258
|
const methodProtectedBy = Reflect.getOwnMetadata(import_core2.GUARD_PROTECTEDBY_METADATA, prototype, methodName) ?? [];
|
|
203
259
|
const allProtectedBy = [
|
|
204
|
-
...
|
|
260
|
+
...meta.protectedBy,
|
|
205
261
|
...methodProtectedBy
|
|
206
262
|
];
|
|
207
263
|
if (allProtectedBy.length > 0) {
|
|
208
264
|
annotations["celerity.handler.guard.protectedBy"] = allProtectedBy;
|
|
209
265
|
}
|
|
210
|
-
if (
|
|
211
|
-
annotations["celerity.handler.guard.custom"] =
|
|
266
|
+
if (meta.customGuardName) {
|
|
267
|
+
annotations["celerity.handler.guard.custom"] = meta.customGuardName;
|
|
212
268
|
}
|
|
213
269
|
const isPublic = Reflect.getOwnMetadata(import_core2.PUBLIC_METADATA, prototype, methodName) === true;
|
|
214
270
|
if (isPublic) {
|
|
@@ -216,57 +272,206 @@ function buildMethodAnnotations(classMeta, prototype, methodName, httpMethod, fu
|
|
|
216
272
|
}
|
|
217
273
|
const methodCustomMetadata = Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, prototype, methodName) ?? {};
|
|
218
274
|
const customMetadata = {
|
|
219
|
-
...
|
|
275
|
+
...meta.customMetadata,
|
|
220
276
|
...methodCustomMetadata
|
|
221
277
|
};
|
|
222
278
|
for (const [key, value] of Object.entries(customMetadata)) {
|
|
223
279
|
if (value === void 0) continue;
|
|
224
280
|
annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
|
|
225
281
|
}
|
|
282
|
+
const methodResourceRefs = Reflect.getOwnMetadata(import_core2.USE_RESOURCE_METADATA, prototype, methodName) ?? [];
|
|
283
|
+
const allResourceRefs = [
|
|
284
|
+
.../* @__PURE__ */ new Set([
|
|
285
|
+
...meta.resourceRefs,
|
|
286
|
+
...methodResourceRefs
|
|
287
|
+
])
|
|
288
|
+
];
|
|
289
|
+
if (allResourceRefs.length > 0) {
|
|
290
|
+
annotations["celerity.handler.resource.ref"] = allResourceRefs;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
__name(appendSharedAnnotations, "appendSharedAnnotations");
|
|
294
|
+
function buildHttpAnnotations(meta, prototype, methodName, httpMethod, fullPath) {
|
|
295
|
+
const annotations = {};
|
|
296
|
+
annotations["celerity.handler.http"] = true;
|
|
297
|
+
annotations["celerity.handler.http.method"] = httpMethod;
|
|
298
|
+
annotations["celerity.handler.http.path"] = fullPath;
|
|
299
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
300
|
+
return annotations;
|
|
301
|
+
}
|
|
302
|
+
__name(buildHttpAnnotations, "buildHttpAnnotations");
|
|
303
|
+
function buildWebSocketAnnotations(meta, prototype, methodName, wsEvent) {
|
|
304
|
+
const annotations = {};
|
|
305
|
+
annotations["celerity.handler.websocket"] = true;
|
|
306
|
+
annotations["celerity.handler.websocket.route"] = wsEvent.route;
|
|
307
|
+
annotations["celerity.handler.websocket.eventType"] = wsEvent.eventType;
|
|
308
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
309
|
+
return annotations;
|
|
310
|
+
}
|
|
311
|
+
__name(buildWebSocketAnnotations, "buildWebSocketAnnotations");
|
|
312
|
+
function buildConsumerAnnotations(meta, prototype, methodName, consumerHandler) {
|
|
313
|
+
const annotations = {};
|
|
314
|
+
annotations["celerity.handler.consumer"] = true;
|
|
315
|
+
if (meta.sourceId) {
|
|
316
|
+
annotations["celerity.handler.consumer.sourceId"] = meta.sourceId;
|
|
317
|
+
}
|
|
318
|
+
if (consumerHandler.route) {
|
|
319
|
+
annotations["celerity.handler.consumer.route"] = consumerHandler.route;
|
|
320
|
+
}
|
|
321
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
322
|
+
return annotations;
|
|
323
|
+
}
|
|
324
|
+
__name(buildConsumerAnnotations, "buildConsumerAnnotations");
|
|
325
|
+
function buildScheduleAnnotations(meta, prototype, methodName, scheduleMeta) {
|
|
326
|
+
const annotations = {};
|
|
327
|
+
annotations["celerity.handler.schedule"] = true;
|
|
328
|
+
if (scheduleMeta.scheduleId) {
|
|
329
|
+
annotations["celerity.handler.schedule.scheduleId"] = scheduleMeta.scheduleId;
|
|
330
|
+
}
|
|
331
|
+
if (scheduleMeta.schedule) {
|
|
332
|
+
annotations["celerity.handler.schedule.expression"] = scheduleMeta.schedule;
|
|
333
|
+
}
|
|
334
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
335
|
+
return annotations;
|
|
336
|
+
}
|
|
337
|
+
__name(buildScheduleAnnotations, "buildScheduleAnnotations");
|
|
338
|
+
function buildCustomAnnotations(meta, prototype, methodName, invokeMeta) {
|
|
339
|
+
const annotations = {};
|
|
340
|
+
annotations["celerity.handler.custom"] = true;
|
|
341
|
+
annotations["celerity.handler.custom.name"] = invokeMeta.name;
|
|
342
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
226
343
|
return annotations;
|
|
227
344
|
}
|
|
228
|
-
__name(
|
|
229
|
-
function
|
|
230
|
-
const
|
|
231
|
-
if (!
|
|
345
|
+
__name(buildCustomAnnotations, "buildCustomAnnotations");
|
|
346
|
+
function serializeClassHandlers(controllerClass, sourceFile, options) {
|
|
347
|
+
const meta = extractControllerMeta(controllerClass);
|
|
348
|
+
if (!meta) return [];
|
|
232
349
|
const className = controllerClass.name;
|
|
233
350
|
const prototype = controllerClass.prototype;
|
|
234
351
|
const methods = Object.getOwnPropertyNames(prototype).filter((n) => n !== "constructor");
|
|
235
352
|
const entries = [];
|
|
236
353
|
for (const methodName of methods) {
|
|
237
|
-
const
|
|
238
|
-
if (
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
}
|
|
354
|
+
const typeEntry = serializeControllerTypeMethod(meta, className, prototype, methodName, sourceFile, options);
|
|
355
|
+
if (typeEntry) entries.push(typeEntry);
|
|
356
|
+
const scheduleMeta = Reflect.getOwnMetadata(import_core2.SCHEDULE_HANDLER_METADATA, prototype, methodName);
|
|
357
|
+
if (scheduleMeta) {
|
|
358
|
+
entries.push({
|
|
359
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
360
|
+
className,
|
|
361
|
+
methodName,
|
|
362
|
+
sourceFile,
|
|
363
|
+
handlerType: "schedule",
|
|
364
|
+
annotations: buildScheduleAnnotations(meta, prototype, methodName, scheduleMeta),
|
|
365
|
+
spec: {
|
|
366
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
367
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
368
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
const invokeMeta = Reflect.getOwnMetadata(import_core2.INVOKE_METADATA, prototype, methodName);
|
|
373
|
+
if (invokeMeta) {
|
|
374
|
+
entries.push({
|
|
375
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
376
|
+
className,
|
|
377
|
+
methodName,
|
|
378
|
+
sourceFile,
|
|
379
|
+
handlerType: "custom",
|
|
380
|
+
annotations: buildCustomAnnotations(meta, prototype, methodName, invokeMeta),
|
|
381
|
+
spec: {
|
|
382
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
383
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
384
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
255
388
|
}
|
|
256
389
|
return entries;
|
|
257
390
|
}
|
|
258
|
-
__name(
|
|
391
|
+
__name(serializeClassHandlers, "serializeClassHandlers");
|
|
392
|
+
function serializeControllerTypeMethod(meta, className, prototype, methodName, sourceFile, options) {
|
|
393
|
+
switch (meta.controllerType) {
|
|
394
|
+
case "http":
|
|
395
|
+
return serializeHttpMethod(meta, className, prototype, methodName, sourceFile, options);
|
|
396
|
+
case "websocket":
|
|
397
|
+
return serializeWebSocketMethod(meta, className, prototype, methodName, sourceFile, options);
|
|
398
|
+
case "consumer":
|
|
399
|
+
return serializeConsumerMethod(meta, className, prototype, methodName, sourceFile, options);
|
|
400
|
+
default:
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
__name(serializeControllerTypeMethod, "serializeControllerTypeMethod");
|
|
405
|
+
function serializeHttpMethod(meta, className, prototype, methodName, sourceFile, options) {
|
|
406
|
+
const httpMethod = Reflect.getOwnMetadata(import_core2.HTTP_METHOD_METADATA, prototype, methodName);
|
|
407
|
+
if (!httpMethod) return null;
|
|
408
|
+
const routePath = Reflect.getOwnMetadata(import_core2.ROUTE_PATH_METADATA, prototype, methodName) ?? "/";
|
|
409
|
+
const fullPath = (0, import_common.joinHandlerPath)(meta.prefix, routePath);
|
|
410
|
+
return {
|
|
411
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
412
|
+
className,
|
|
413
|
+
methodName,
|
|
414
|
+
sourceFile,
|
|
415
|
+
handlerType: "http",
|
|
416
|
+
annotations: buildHttpAnnotations(meta, prototype, methodName, httpMethod, fullPath),
|
|
417
|
+
spec: {
|
|
418
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
419
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
420
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
__name(serializeHttpMethod, "serializeHttpMethod");
|
|
425
|
+
function serializeWebSocketMethod(meta, className, prototype, methodName, sourceFile, options) {
|
|
426
|
+
const wsEvent = Reflect.getOwnMetadata(import_core2.WEBSOCKET_EVENT_METADATA, prototype, methodName);
|
|
427
|
+
if (!wsEvent) return null;
|
|
428
|
+
return {
|
|
429
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
430
|
+
className,
|
|
431
|
+
methodName,
|
|
432
|
+
sourceFile,
|
|
433
|
+
handlerType: "websocket",
|
|
434
|
+
annotations: buildWebSocketAnnotations(meta, prototype, methodName, wsEvent),
|
|
435
|
+
spec: {
|
|
436
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
437
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
438
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
__name(serializeWebSocketMethod, "serializeWebSocketMethod");
|
|
443
|
+
function serializeConsumerMethod(meta, className, prototype, methodName, sourceFile, options) {
|
|
444
|
+
const consumerHandler = Reflect.getOwnMetadata(import_core2.CONSUMER_HANDLER_METADATA, prototype, methodName);
|
|
445
|
+
if (!consumerHandler) return null;
|
|
446
|
+
return {
|
|
447
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
448
|
+
className,
|
|
449
|
+
methodName,
|
|
450
|
+
sourceFile,
|
|
451
|
+
handlerType: "consumer",
|
|
452
|
+
annotations: buildConsumerAnnotations(meta, prototype, methodName, consumerHandler),
|
|
453
|
+
spec: {
|
|
454
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
455
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
456
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
__name(serializeConsumerMethod, "serializeConsumerMethod");
|
|
259
461
|
function serializeFunctionHandler(definition, sourceFile, options) {
|
|
462
|
+
const supported = [
|
|
463
|
+
"http",
|
|
464
|
+
"websocket",
|
|
465
|
+
"consumer",
|
|
466
|
+
"schedule",
|
|
467
|
+
"custom"
|
|
468
|
+
];
|
|
469
|
+
if (!supported.includes(definition.type)) return null;
|
|
260
470
|
const exportName = definition.metadata.handlerName ?? "handler";
|
|
261
471
|
const customMetadata = definition.metadata.customMetadata ?? {};
|
|
472
|
+
const handlerType = definition.type;
|
|
262
473
|
const annotations = {};
|
|
263
|
-
|
|
264
|
-
const method = definition.metadata.method;
|
|
265
|
-
if (path !== void 0 && method !== void 0) {
|
|
266
|
-
annotations["celerity.handler.http"] = true;
|
|
267
|
-
annotations["celerity.handler.http.method"] = method;
|
|
268
|
-
annotations["celerity.handler.http.path"] = path;
|
|
269
|
-
}
|
|
474
|
+
buildFunctionTypeAnnotations(annotations, definition);
|
|
270
475
|
for (const [key, value] of Object.entries(customMetadata)) {
|
|
271
476
|
if (value === void 0) continue;
|
|
272
477
|
annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
|
|
@@ -275,6 +480,7 @@ function serializeFunctionHandler(definition, sourceFile, options) {
|
|
|
275
480
|
resourceName: deriveFunctionResourceName(exportName),
|
|
276
481
|
exportName,
|
|
277
482
|
sourceFile,
|
|
483
|
+
handlerType,
|
|
278
484
|
...Object.keys(annotations).length > 0 ? {
|
|
279
485
|
annotations
|
|
280
486
|
} : {},
|
|
@@ -286,6 +492,122 @@ function serializeFunctionHandler(definition, sourceFile, options) {
|
|
|
286
492
|
};
|
|
287
493
|
}
|
|
288
494
|
__name(serializeFunctionHandler, "serializeFunctionHandler");
|
|
495
|
+
function buildFunctionTypeAnnotations(annotations, definition) {
|
|
496
|
+
const meta = definition.metadata;
|
|
497
|
+
switch (definition.type) {
|
|
498
|
+
case "http": {
|
|
499
|
+
const path = meta.path;
|
|
500
|
+
const method = meta.method;
|
|
501
|
+
if (path !== void 0 && method !== void 0) {
|
|
502
|
+
annotations["celerity.handler.http"] = true;
|
|
503
|
+
annotations["celerity.handler.http.method"] = method;
|
|
504
|
+
annotations["celerity.handler.http.path"] = path;
|
|
505
|
+
}
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
case "websocket": {
|
|
509
|
+
annotations["celerity.handler.websocket"] = true;
|
|
510
|
+
const route = meta.route;
|
|
511
|
+
if (route) {
|
|
512
|
+
annotations["celerity.handler.websocket.route"] = route;
|
|
513
|
+
}
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
case "consumer": {
|
|
517
|
+
annotations["celerity.handler.consumer"] = true;
|
|
518
|
+
const route = meta.route;
|
|
519
|
+
if (route) {
|
|
520
|
+
annotations["celerity.handler.consumer.route"] = route;
|
|
521
|
+
}
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
524
|
+
case "schedule": {
|
|
525
|
+
annotations["celerity.handler.schedule"] = true;
|
|
526
|
+
const scheduleId = meta.scheduleId;
|
|
527
|
+
if (scheduleId) {
|
|
528
|
+
annotations["celerity.handler.schedule.scheduleId"] = scheduleId;
|
|
529
|
+
}
|
|
530
|
+
const schedule = meta.schedule;
|
|
531
|
+
if (schedule) {
|
|
532
|
+
annotations["celerity.handler.schedule.expression"] = schedule;
|
|
533
|
+
}
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
case "custom": {
|
|
537
|
+
annotations["celerity.handler.custom"] = true;
|
|
538
|
+
const name = meta.name;
|
|
539
|
+
if (name) {
|
|
540
|
+
annotations["celerity.handler.custom.name"] = name;
|
|
541
|
+
}
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
__name(buildFunctionTypeAnnotations, "buildFunctionTypeAnnotations");
|
|
547
|
+
function extractGuardMeta(guardClass) {
|
|
548
|
+
const guardName = Reflect.getOwnMetadata(import_core2.GUARD_CUSTOM_METADATA, guardClass);
|
|
549
|
+
if (!guardName) return null;
|
|
550
|
+
return {
|
|
551
|
+
guardName,
|
|
552
|
+
customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, guardClass) ?? {}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
__name(extractGuardMeta, "extractGuardMeta");
|
|
556
|
+
function serializeClassGuard(guardClass, sourceFile, options) {
|
|
557
|
+
const meta = extractGuardMeta(guardClass);
|
|
558
|
+
if (!meta) return null;
|
|
559
|
+
const className = guardClass.name;
|
|
560
|
+
const methodName = "check";
|
|
561
|
+
const annotations = {
|
|
562
|
+
"celerity.handler.guard.custom": meta.guardName
|
|
563
|
+
};
|
|
564
|
+
for (const [key, value] of Object.entries(meta.customMetadata)) {
|
|
565
|
+
if (value === void 0) continue;
|
|
566
|
+
annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
|
|
567
|
+
}
|
|
568
|
+
return {
|
|
569
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
570
|
+
guardName: meta.guardName,
|
|
571
|
+
sourceFile,
|
|
572
|
+
guardType: "class",
|
|
573
|
+
className,
|
|
574
|
+
annotations,
|
|
575
|
+
spec: {
|
|
576
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
577
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
578
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
__name(serializeClassGuard, "serializeClassGuard");
|
|
583
|
+
function serializeFunctionGuard(definition, sourceFile, options) {
|
|
584
|
+
const guardName = definition.name;
|
|
585
|
+
if (!guardName) return null;
|
|
586
|
+
const meta = definition.metadata ?? {};
|
|
587
|
+
const customMetadata = meta.customMetadata ?? {};
|
|
588
|
+
const annotations = {
|
|
589
|
+
"celerity.handler.guard.custom": guardName
|
|
590
|
+
};
|
|
591
|
+
for (const [key, value] of Object.entries(customMetadata)) {
|
|
592
|
+
if (value === void 0) continue;
|
|
593
|
+
annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
|
|
594
|
+
}
|
|
595
|
+
const exportName = guardName;
|
|
596
|
+
return {
|
|
597
|
+
resourceName: deriveFunctionResourceName(exportName),
|
|
598
|
+
guardName,
|
|
599
|
+
sourceFile,
|
|
600
|
+
guardType: "function",
|
|
601
|
+
exportName,
|
|
602
|
+
annotations,
|
|
603
|
+
spec: {
|
|
604
|
+
handlerName: exportName,
|
|
605
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
606
|
+
handler: deriveFunctionHandlerFunction(sourceFile, exportName)
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
__name(serializeFunctionGuard, "serializeFunctionGuard");
|
|
289
611
|
function serializeAnnotationValue(value) {
|
|
290
612
|
if (typeof value === "boolean") return value;
|
|
291
613
|
if (typeof value === "string") return value;
|