@celerity-sdk/cli 0.3.1 → 0.5.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 +372 -49
- package/dist/extract/cli.cjs.map +1 -1
- package/dist/extract/cli.js +372 -49
- package/dist/extract/cli.js.map +1 -1
- package/dist/index.cjs +373 -50
- 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 +372 -49
- 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.source` | Blueprint resource name 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.source` | Blueprint resource name from `@ScheduleHandler` |
|
|
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
|
@@ -31,6 +31,7 @@ var import_debug2 = __toESM(require("debug"), 1);
|
|
|
31
31
|
// src/extract/metadata-app.ts
|
|
32
32
|
var import_reflect_metadata = require("reflect-metadata");
|
|
33
33
|
var import_debug = __toESM(require("debug"), 1);
|
|
34
|
+
var import_common = require("@celerity-sdk/common");
|
|
34
35
|
var import_core = require("@celerity-sdk/core");
|
|
35
36
|
var debug = (0, import_debug.default)("celerity:cli");
|
|
36
37
|
function scanProvider(provider, seenTokens) {
|
|
@@ -57,10 +58,12 @@ function buildScannedModule(rootModule) {
|
|
|
57
58
|
const graph = (0, import_core.buildModuleGraph)(rootModule);
|
|
58
59
|
const controllerClasses = [];
|
|
59
60
|
const functionHandlers = [];
|
|
61
|
+
const guardClasses = [];
|
|
62
|
+
const functionGuards = [];
|
|
60
63
|
const providers = [];
|
|
61
64
|
const seenTokens = /* @__PURE__ */ new Set();
|
|
62
65
|
for (const [moduleClass, node] of graph) {
|
|
63
|
-
debug("scan: module %s \u2014 %d providers, %d controllers", moduleClass.name, node.providers.length, node.controllers.length);
|
|
66
|
+
debug("scan: module %s \u2014 %d providers, %d controllers, %d guards", moduleClass.name, node.providers.length, node.controllers.length, node.guards.length);
|
|
64
67
|
for (const provider of node.providers) {
|
|
65
68
|
const scanned = scanProvider(provider, seenTokens);
|
|
66
69
|
if (scanned) providers.push(scanned);
|
|
@@ -76,11 +79,28 @@ function buildScannedModule(rootModule) {
|
|
|
76
79
|
});
|
|
77
80
|
}
|
|
78
81
|
}
|
|
82
|
+
for (const guard of node.guards) {
|
|
83
|
+
if (typeof guard === "function") {
|
|
84
|
+
guardClasses.push(guard);
|
|
85
|
+
if (!seenTokens.has(guard)) {
|
|
86
|
+
seenTokens.add(guard);
|
|
87
|
+
providers.push({
|
|
88
|
+
token: guard,
|
|
89
|
+
providerType: "class",
|
|
90
|
+
dependencies: (0, import_core.getClassDependencyTokens)(guard)
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
functionGuards.push(guard);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
79
97
|
functionHandlers.push(...node.functionHandlers);
|
|
80
98
|
}
|
|
81
99
|
return {
|
|
82
100
|
controllerClasses,
|
|
83
101
|
functionHandlers,
|
|
102
|
+
guardClasses,
|
|
103
|
+
functionGuards,
|
|
84
104
|
providers
|
|
85
105
|
};
|
|
86
106
|
}
|
|
@@ -100,7 +120,7 @@ function validateScannedDependencies(scanned) {
|
|
|
100
120
|
}
|
|
101
121
|
} else if (typeof dep === "function") {
|
|
102
122
|
walk(dep, (0, import_core.getClassDependencyTokens)(dep));
|
|
103
|
-
} else {
|
|
123
|
+
} else if (!(0, import_common.isResourceLayerToken)(dep)) {
|
|
104
124
|
diagnostics.push({
|
|
105
125
|
consumer: serializeToken(token),
|
|
106
126
|
dependency: serializeToken(dep)
|
|
@@ -127,7 +147,7 @@ var import_reflect_metadata2 = require("reflect-metadata");
|
|
|
127
147
|
var import_core2 = require("@celerity-sdk/core");
|
|
128
148
|
|
|
129
149
|
// src/extract/path-utils.ts
|
|
130
|
-
var
|
|
150
|
+
var import_common2 = require("@celerity-sdk/common");
|
|
131
151
|
|
|
132
152
|
// src/extract/identity.ts
|
|
133
153
|
var import_node_path = require("path");
|
|
@@ -165,8 +185,9 @@ __name(deriveCodeLocation, "deriveCodeLocation");
|
|
|
165
185
|
function serializeManifest(scanned, sourceFile, options) {
|
|
166
186
|
const handlers = [];
|
|
167
187
|
const functionHandlers = [];
|
|
188
|
+
const guardHandlers = [];
|
|
168
189
|
for (const controllerClass of scanned.controllerClasses) {
|
|
169
|
-
const entries =
|
|
190
|
+
const entries = serializeClassHandlers(controllerClass, sourceFile, options);
|
|
170
191
|
handlers.push(...entries);
|
|
171
192
|
}
|
|
172
193
|
for (const fnHandler of scanned.functionHandlers) {
|
|
@@ -175,40 +196,76 @@ function serializeManifest(scanned, sourceFile, options) {
|
|
|
175
196
|
functionHandlers.push(entry);
|
|
176
197
|
}
|
|
177
198
|
}
|
|
199
|
+
for (const guardClass of scanned.guardClasses) {
|
|
200
|
+
const entry = serializeClassGuard(guardClass, sourceFile, options);
|
|
201
|
+
if (entry) {
|
|
202
|
+
guardHandlers.push(entry);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
for (const fnGuard of scanned.functionGuards) {
|
|
206
|
+
const entry = serializeFunctionGuard(fnGuard, sourceFile, options);
|
|
207
|
+
if (entry) {
|
|
208
|
+
guardHandlers.push(entry);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
178
211
|
return {
|
|
179
212
|
version: "1.0.0",
|
|
180
213
|
handlers,
|
|
181
214
|
functionHandlers,
|
|
215
|
+
guardHandlers,
|
|
182
216
|
dependencyGraph: serializeDependencyGraph(scanned)
|
|
183
217
|
};
|
|
184
218
|
}
|
|
185
219
|
__name(serializeManifest, "serializeManifest");
|
|
186
|
-
function
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
220
|
+
function extractControllerMeta(controllerClass) {
|
|
221
|
+
const httpMeta = Reflect.getOwnMetadata(import_core2.CONTROLLER_METADATA, controllerClass);
|
|
222
|
+
if (httpMeta) {
|
|
223
|
+
return {
|
|
224
|
+
controllerType: "http",
|
|
225
|
+
prefix: httpMeta.prefix ?? "",
|
|
226
|
+
...extractSharedClassMeta(controllerClass)
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const isWebSocket = Reflect.getOwnMetadata(import_core2.WEBSOCKET_CONTROLLER_METADATA, controllerClass);
|
|
230
|
+
if (isWebSocket) {
|
|
231
|
+
return {
|
|
232
|
+
controllerType: "websocket",
|
|
233
|
+
prefix: "",
|
|
234
|
+
...extractSharedClassMeta(controllerClass)
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
const consumerMeta = Reflect.getOwnMetadata(import_core2.CONSUMER_METADATA, controllerClass);
|
|
238
|
+
if (consumerMeta) {
|
|
239
|
+
return {
|
|
240
|
+
controllerType: "consumer",
|
|
241
|
+
prefix: "",
|
|
242
|
+
source: consumerMeta.source,
|
|
243
|
+
...extractSharedClassMeta(controllerClass)
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
__name(extractControllerMeta, "extractControllerMeta");
|
|
249
|
+
function extractSharedClassMeta(controllerClass) {
|
|
189
250
|
return {
|
|
190
|
-
prefix: controllerMeta.prefix ?? "",
|
|
191
251
|
protectedBy: Reflect.getOwnMetadata(import_core2.GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [],
|
|
192
252
|
customGuardName: Reflect.getOwnMetadata(import_core2.GUARD_CUSTOM_METADATA, controllerClass),
|
|
193
|
-
customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, controllerClass) ?? {}
|
|
253
|
+
customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, controllerClass) ?? {},
|
|
254
|
+
resourceRefs: Reflect.getOwnMetadata(import_core2.USE_RESOURCE_METADATA, controllerClass) ?? []
|
|
194
255
|
};
|
|
195
256
|
}
|
|
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;
|
|
257
|
+
__name(extractSharedClassMeta, "extractSharedClassMeta");
|
|
258
|
+
function appendSharedAnnotations(annotations, meta, prototype, methodName) {
|
|
202
259
|
const methodProtectedBy = Reflect.getOwnMetadata(import_core2.GUARD_PROTECTEDBY_METADATA, prototype, methodName) ?? [];
|
|
203
260
|
const allProtectedBy = [
|
|
204
|
-
...
|
|
261
|
+
...meta.protectedBy,
|
|
205
262
|
...methodProtectedBy
|
|
206
263
|
];
|
|
207
264
|
if (allProtectedBy.length > 0) {
|
|
208
265
|
annotations["celerity.handler.guard.protectedBy"] = allProtectedBy;
|
|
209
266
|
}
|
|
210
|
-
if (
|
|
211
|
-
annotations["celerity.handler.guard.custom"] =
|
|
267
|
+
if (meta.customGuardName) {
|
|
268
|
+
annotations["celerity.handler.guard.custom"] = meta.customGuardName;
|
|
212
269
|
}
|
|
213
270
|
const isPublic = Reflect.getOwnMetadata(import_core2.PUBLIC_METADATA, prototype, methodName) === true;
|
|
214
271
|
if (isPublic) {
|
|
@@ -216,57 +273,206 @@ function buildMethodAnnotations(classMeta, prototype, methodName, httpMethod, fu
|
|
|
216
273
|
}
|
|
217
274
|
const methodCustomMetadata = Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, prototype, methodName) ?? {};
|
|
218
275
|
const customMetadata = {
|
|
219
|
-
...
|
|
276
|
+
...meta.customMetadata,
|
|
220
277
|
...methodCustomMetadata
|
|
221
278
|
};
|
|
222
279
|
for (const [key, value] of Object.entries(customMetadata)) {
|
|
223
280
|
if (value === void 0) continue;
|
|
224
281
|
annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
|
|
225
282
|
}
|
|
283
|
+
const methodResourceRefs = Reflect.getOwnMetadata(import_core2.USE_RESOURCE_METADATA, prototype, methodName) ?? [];
|
|
284
|
+
const allResourceRefs = [
|
|
285
|
+
.../* @__PURE__ */ new Set([
|
|
286
|
+
...meta.resourceRefs,
|
|
287
|
+
...methodResourceRefs
|
|
288
|
+
])
|
|
289
|
+
];
|
|
290
|
+
if (allResourceRefs.length > 0) {
|
|
291
|
+
annotations["celerity.handler.resource.ref"] = allResourceRefs;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
__name(appendSharedAnnotations, "appendSharedAnnotations");
|
|
295
|
+
function buildHttpAnnotations(meta, prototype, methodName, httpMethod, fullPath) {
|
|
296
|
+
const annotations = {};
|
|
297
|
+
annotations["celerity.handler.http"] = true;
|
|
298
|
+
annotations["celerity.handler.http.method"] = httpMethod;
|
|
299
|
+
annotations["celerity.handler.http.path"] = fullPath;
|
|
300
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
301
|
+
return annotations;
|
|
302
|
+
}
|
|
303
|
+
__name(buildHttpAnnotations, "buildHttpAnnotations");
|
|
304
|
+
function buildWebSocketAnnotations(meta, prototype, methodName, wsEvent) {
|
|
305
|
+
const annotations = {};
|
|
306
|
+
annotations["celerity.handler.websocket"] = true;
|
|
307
|
+
annotations["celerity.handler.websocket.route"] = wsEvent.route;
|
|
308
|
+
annotations["celerity.handler.websocket.eventType"] = wsEvent.eventType;
|
|
309
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
310
|
+
return annotations;
|
|
311
|
+
}
|
|
312
|
+
__name(buildWebSocketAnnotations, "buildWebSocketAnnotations");
|
|
313
|
+
function buildConsumerAnnotations(meta, prototype, methodName, consumerHandler) {
|
|
314
|
+
const annotations = {};
|
|
315
|
+
annotations["celerity.handler.consumer"] = true;
|
|
316
|
+
if (meta.source) {
|
|
317
|
+
annotations["celerity.handler.consumer.source"] = meta.source;
|
|
318
|
+
}
|
|
319
|
+
if (consumerHandler.route) {
|
|
320
|
+
annotations["celerity.handler.consumer.route"] = consumerHandler.route;
|
|
321
|
+
}
|
|
322
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
323
|
+
return annotations;
|
|
324
|
+
}
|
|
325
|
+
__name(buildConsumerAnnotations, "buildConsumerAnnotations");
|
|
326
|
+
function buildScheduleAnnotations(meta, prototype, methodName, scheduleMeta) {
|
|
327
|
+
const annotations = {};
|
|
328
|
+
annotations["celerity.handler.schedule"] = true;
|
|
329
|
+
if (scheduleMeta.source) {
|
|
330
|
+
annotations["celerity.handler.schedule.source"] = scheduleMeta.source;
|
|
331
|
+
}
|
|
332
|
+
if (scheduleMeta.schedule) {
|
|
333
|
+
annotations["celerity.handler.schedule.expression"] = scheduleMeta.schedule;
|
|
334
|
+
}
|
|
335
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
226
336
|
return annotations;
|
|
227
337
|
}
|
|
228
|
-
__name(
|
|
229
|
-
function
|
|
230
|
-
const
|
|
231
|
-
|
|
338
|
+
__name(buildScheduleAnnotations, "buildScheduleAnnotations");
|
|
339
|
+
function buildCustomAnnotations(meta, prototype, methodName, invokeMeta) {
|
|
340
|
+
const annotations = {};
|
|
341
|
+
annotations["celerity.handler.custom"] = true;
|
|
342
|
+
annotations["celerity.handler.custom.name"] = invokeMeta.name;
|
|
343
|
+
appendSharedAnnotations(annotations, meta, prototype, methodName);
|
|
344
|
+
return annotations;
|
|
345
|
+
}
|
|
346
|
+
__name(buildCustomAnnotations, "buildCustomAnnotations");
|
|
347
|
+
function serializeClassHandlers(controllerClass, sourceFile, options) {
|
|
348
|
+
const meta = extractControllerMeta(controllerClass);
|
|
349
|
+
if (!meta) return [];
|
|
232
350
|
const className = controllerClass.name;
|
|
233
351
|
const prototype = controllerClass.prototype;
|
|
234
352
|
const methods = Object.getOwnPropertyNames(prototype).filter((n) => n !== "constructor");
|
|
235
353
|
const entries = [];
|
|
236
354
|
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
|
-
}
|
|
355
|
+
const typeEntry = serializeControllerTypeMethod(meta, className, prototype, methodName, sourceFile, options);
|
|
356
|
+
if (typeEntry) entries.push(typeEntry);
|
|
357
|
+
const scheduleMeta = Reflect.getOwnMetadata(import_core2.SCHEDULE_HANDLER_METADATA, prototype, methodName);
|
|
358
|
+
if (scheduleMeta) {
|
|
359
|
+
entries.push({
|
|
360
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
361
|
+
className,
|
|
362
|
+
methodName,
|
|
363
|
+
sourceFile,
|
|
364
|
+
handlerType: "schedule",
|
|
365
|
+
annotations: buildScheduleAnnotations(meta, prototype, methodName, scheduleMeta),
|
|
366
|
+
spec: {
|
|
367
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
368
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
369
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
const invokeMeta = Reflect.getOwnMetadata(import_core2.INVOKE_METADATA, prototype, methodName);
|
|
374
|
+
if (invokeMeta) {
|
|
375
|
+
entries.push({
|
|
376
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
377
|
+
className,
|
|
378
|
+
methodName,
|
|
379
|
+
sourceFile,
|
|
380
|
+
handlerType: "custom",
|
|
381
|
+
annotations: buildCustomAnnotations(meta, prototype, methodName, invokeMeta),
|
|
382
|
+
spec: {
|
|
383
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
384
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
385
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
255
389
|
}
|
|
256
390
|
return entries;
|
|
257
391
|
}
|
|
258
|
-
__name(
|
|
392
|
+
__name(serializeClassHandlers, "serializeClassHandlers");
|
|
393
|
+
function serializeControllerTypeMethod(meta, className, prototype, methodName, sourceFile, options) {
|
|
394
|
+
switch (meta.controllerType) {
|
|
395
|
+
case "http":
|
|
396
|
+
return serializeHttpMethod(meta, className, prototype, methodName, sourceFile, options);
|
|
397
|
+
case "websocket":
|
|
398
|
+
return serializeWebSocketMethod(meta, className, prototype, methodName, sourceFile, options);
|
|
399
|
+
case "consumer":
|
|
400
|
+
return serializeConsumerMethod(meta, className, prototype, methodName, sourceFile, options);
|
|
401
|
+
default:
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
__name(serializeControllerTypeMethod, "serializeControllerTypeMethod");
|
|
406
|
+
function serializeHttpMethod(meta, className, prototype, methodName, sourceFile, options) {
|
|
407
|
+
const httpMethod = Reflect.getOwnMetadata(import_core2.HTTP_METHOD_METADATA, prototype, methodName);
|
|
408
|
+
if (!httpMethod) return null;
|
|
409
|
+
const routePath = Reflect.getOwnMetadata(import_core2.ROUTE_PATH_METADATA, prototype, methodName) ?? "/";
|
|
410
|
+
const fullPath = (0, import_common2.joinHandlerPath)(meta.prefix, routePath);
|
|
411
|
+
return {
|
|
412
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
413
|
+
className,
|
|
414
|
+
methodName,
|
|
415
|
+
sourceFile,
|
|
416
|
+
handlerType: "http",
|
|
417
|
+
annotations: buildHttpAnnotations(meta, prototype, methodName, httpMethod, fullPath),
|
|
418
|
+
spec: {
|
|
419
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
420
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
421
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
__name(serializeHttpMethod, "serializeHttpMethod");
|
|
426
|
+
function serializeWebSocketMethod(meta, className, prototype, methodName, sourceFile, options) {
|
|
427
|
+
const wsEvent = Reflect.getOwnMetadata(import_core2.WEBSOCKET_EVENT_METADATA, prototype, methodName);
|
|
428
|
+
if (!wsEvent) return null;
|
|
429
|
+
return {
|
|
430
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
431
|
+
className,
|
|
432
|
+
methodName,
|
|
433
|
+
sourceFile,
|
|
434
|
+
handlerType: "websocket",
|
|
435
|
+
annotations: buildWebSocketAnnotations(meta, prototype, methodName, wsEvent),
|
|
436
|
+
spec: {
|
|
437
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
438
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
439
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
__name(serializeWebSocketMethod, "serializeWebSocketMethod");
|
|
444
|
+
function serializeConsumerMethod(meta, className, prototype, methodName, sourceFile, options) {
|
|
445
|
+
const consumerHandler = Reflect.getOwnMetadata(import_core2.CONSUMER_HANDLER_METADATA, prototype, methodName);
|
|
446
|
+
if (!consumerHandler) return null;
|
|
447
|
+
return {
|
|
448
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
449
|
+
className,
|
|
450
|
+
methodName,
|
|
451
|
+
sourceFile,
|
|
452
|
+
handlerType: "consumer",
|
|
453
|
+
annotations: buildConsumerAnnotations(meta, prototype, methodName, consumerHandler),
|
|
454
|
+
spec: {
|
|
455
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
456
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
457
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
__name(serializeConsumerMethod, "serializeConsumerMethod");
|
|
259
462
|
function serializeFunctionHandler(definition, sourceFile, options) {
|
|
463
|
+
const supported = [
|
|
464
|
+
"http",
|
|
465
|
+
"websocket",
|
|
466
|
+
"consumer",
|
|
467
|
+
"schedule",
|
|
468
|
+
"custom"
|
|
469
|
+
];
|
|
470
|
+
if (!supported.includes(definition.type)) return null;
|
|
260
471
|
const exportName = definition.metadata.handlerName ?? "handler";
|
|
261
472
|
const customMetadata = definition.metadata.customMetadata ?? {};
|
|
473
|
+
const handlerType = definition.type;
|
|
262
474
|
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
|
-
}
|
|
475
|
+
buildFunctionTypeAnnotations(annotations, definition);
|
|
270
476
|
for (const [key, value] of Object.entries(customMetadata)) {
|
|
271
477
|
if (value === void 0) continue;
|
|
272
478
|
annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
|
|
@@ -275,6 +481,7 @@ function serializeFunctionHandler(definition, sourceFile, options) {
|
|
|
275
481
|
resourceName: deriveFunctionResourceName(exportName),
|
|
276
482
|
exportName,
|
|
277
483
|
sourceFile,
|
|
484
|
+
handlerType,
|
|
278
485
|
...Object.keys(annotations).length > 0 ? {
|
|
279
486
|
annotations
|
|
280
487
|
} : {},
|
|
@@ -286,6 +493,122 @@ function serializeFunctionHandler(definition, sourceFile, options) {
|
|
|
286
493
|
};
|
|
287
494
|
}
|
|
288
495
|
__name(serializeFunctionHandler, "serializeFunctionHandler");
|
|
496
|
+
function buildFunctionTypeAnnotations(annotations, definition) {
|
|
497
|
+
const meta = definition.metadata;
|
|
498
|
+
switch (definition.type) {
|
|
499
|
+
case "http": {
|
|
500
|
+
const path = meta.path;
|
|
501
|
+
const method = meta.method;
|
|
502
|
+
if (path !== void 0 && method !== void 0) {
|
|
503
|
+
annotations["celerity.handler.http"] = true;
|
|
504
|
+
annotations["celerity.handler.http.method"] = method;
|
|
505
|
+
annotations["celerity.handler.http.path"] = path;
|
|
506
|
+
}
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
case "websocket": {
|
|
510
|
+
annotations["celerity.handler.websocket"] = true;
|
|
511
|
+
const route = meta.route;
|
|
512
|
+
if (route) {
|
|
513
|
+
annotations["celerity.handler.websocket.route"] = route;
|
|
514
|
+
}
|
|
515
|
+
break;
|
|
516
|
+
}
|
|
517
|
+
case "consumer": {
|
|
518
|
+
annotations["celerity.handler.consumer"] = true;
|
|
519
|
+
const route = meta.route;
|
|
520
|
+
if (route) {
|
|
521
|
+
annotations["celerity.handler.consumer.route"] = route;
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
case "schedule": {
|
|
526
|
+
annotations["celerity.handler.schedule"] = true;
|
|
527
|
+
const source = meta.source;
|
|
528
|
+
if (source) {
|
|
529
|
+
annotations["celerity.handler.schedule.source"] = source;
|
|
530
|
+
}
|
|
531
|
+
const schedule = meta.schedule;
|
|
532
|
+
if (schedule) {
|
|
533
|
+
annotations["celerity.handler.schedule.expression"] = schedule;
|
|
534
|
+
}
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
case "custom": {
|
|
538
|
+
annotations["celerity.handler.custom"] = true;
|
|
539
|
+
const name = meta.name;
|
|
540
|
+
if (name) {
|
|
541
|
+
annotations["celerity.handler.custom.name"] = name;
|
|
542
|
+
}
|
|
543
|
+
break;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
__name(buildFunctionTypeAnnotations, "buildFunctionTypeAnnotations");
|
|
548
|
+
function extractGuardMeta(guardClass) {
|
|
549
|
+
const guardName = Reflect.getOwnMetadata(import_core2.GUARD_CUSTOM_METADATA, guardClass);
|
|
550
|
+
if (!guardName) return null;
|
|
551
|
+
return {
|
|
552
|
+
guardName,
|
|
553
|
+
customMetadata: Reflect.getOwnMetadata(import_core2.CUSTOM_METADATA, guardClass) ?? {}
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
__name(extractGuardMeta, "extractGuardMeta");
|
|
557
|
+
function serializeClassGuard(guardClass, sourceFile, options) {
|
|
558
|
+
const meta = extractGuardMeta(guardClass);
|
|
559
|
+
if (!meta) return null;
|
|
560
|
+
const className = guardClass.name;
|
|
561
|
+
const methodName = "check";
|
|
562
|
+
const annotations = {
|
|
563
|
+
"celerity.handler.guard.custom": meta.guardName
|
|
564
|
+
};
|
|
565
|
+
for (const [key, value] of Object.entries(meta.customMetadata)) {
|
|
566
|
+
if (value === void 0) continue;
|
|
567
|
+
annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
|
|
568
|
+
}
|
|
569
|
+
return {
|
|
570
|
+
resourceName: deriveClassResourceName(className, methodName),
|
|
571
|
+
guardName: meta.guardName,
|
|
572
|
+
sourceFile,
|
|
573
|
+
guardType: "class",
|
|
574
|
+
className,
|
|
575
|
+
annotations,
|
|
576
|
+
spec: {
|
|
577
|
+
handlerName: deriveClassHandlerName(className, methodName),
|
|
578
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
579
|
+
handler: deriveClassHandlerFunction(sourceFile, className, methodName)
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
__name(serializeClassGuard, "serializeClassGuard");
|
|
584
|
+
function serializeFunctionGuard(definition, sourceFile, options) {
|
|
585
|
+
const guardName = definition.name;
|
|
586
|
+
if (!guardName) return null;
|
|
587
|
+
const meta = definition.metadata ?? {};
|
|
588
|
+
const customMetadata = meta.customMetadata ?? {};
|
|
589
|
+
const annotations = {
|
|
590
|
+
"celerity.handler.guard.custom": guardName
|
|
591
|
+
};
|
|
592
|
+
for (const [key, value] of Object.entries(customMetadata)) {
|
|
593
|
+
if (value === void 0) continue;
|
|
594
|
+
annotations[`celerity.handler.metadata.${key}`] = serializeAnnotationValue(value);
|
|
595
|
+
}
|
|
596
|
+
const exportName = guardName;
|
|
597
|
+
return {
|
|
598
|
+
resourceName: deriveFunctionResourceName(exportName),
|
|
599
|
+
guardName,
|
|
600
|
+
sourceFile,
|
|
601
|
+
guardType: "function",
|
|
602
|
+
exportName,
|
|
603
|
+
annotations,
|
|
604
|
+
spec: {
|
|
605
|
+
handlerName: exportName,
|
|
606
|
+
codeLocation: deriveCodeLocation(sourceFile, options.projectRoot),
|
|
607
|
+
handler: deriveFunctionHandlerFunction(sourceFile, exportName)
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
__name(serializeFunctionGuard, "serializeFunctionGuard");
|
|
289
612
|
function serializeAnnotationValue(value) {
|
|
290
613
|
if (typeof value === "boolean") return value;
|
|
291
614
|
if (typeof value === "string") return value;
|