@modularizer/plat-client 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/dist/args/coerce.d.ts +54 -0
- package/dist/args/coerce.d.ts.map +1 -0
- package/dist/args/coerce.js +236 -0
- package/dist/args/coerce.js.map +1 -0
- package/dist/args/index.d.ts +2 -0
- package/dist/args/index.d.ts.map +1 -0
- package/dist/args/index.js +2 -0
- package/dist/args/index.js.map +1 -0
- package/dist/args/scalars.d.ts +87 -0
- package/dist/args/scalars.d.ts.map +1 -0
- package/dist/args/scalars.js +22 -0
- package/dist/args/scalars.js.map +1 -0
- package/dist/args/validate.d.ts +23 -0
- package/dist/args/validate.d.ts.map +1 -0
- package/dist/args/validate.js +185 -0
- package/dist/args/validate.js.map +1 -0
- package/dist/args/z2.d.ts +27 -0
- package/dist/args/z2.d.ts.map +1 -0
- package/dist/args/z2.js +24 -0
- package/dist/args/z2.js.map +1 -0
- package/dist/client/css-transport-plugin.d.ts +19 -0
- package/dist/client/css-transport-plugin.d.ts.map +1 -0
- package/dist/client/css-transport-plugin.js +78 -0
- package/dist/client/css-transport-plugin.js.map +1 -0
- package/dist/client/file-transport-plugin.d.ts +28 -0
- package/dist/client/file-transport-plugin.d.ts.map +1 -0
- package/dist/client/file-transport-plugin.js +80 -0
- package/dist/client/file-transport-plugin.js.map +1 -0
- package/dist/client/http-transport-plugin.d.ts +27 -0
- package/dist/client/http-transport-plugin.d.ts.map +1 -0
- package/dist/client/http-transport-plugin.js +48 -0
- package/dist/client/http-transport-plugin.js.map +1 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/openapi-client.d.ts +334 -0
- package/dist/client/openapi-client.d.ts.map +1 -0
- package/dist/client/openapi-client.js +910 -0
- package/dist/client/openapi-client.js.map +1 -0
- package/dist/client/proxy.d.ts +5 -0
- package/dist/client/proxy.d.ts.map +1 -0
- package/dist/client/proxy.js +353 -0
- package/dist/client/proxy.js.map +1 -0
- package/dist/client/request-builder.d.ts +5 -0
- package/dist/client/request-builder.d.ts.map +1 -0
- package/dist/client/request-builder.js +88 -0
- package/dist/client/request-builder.js.map +1 -0
- package/dist/client/rpc-transport-plugin.d.ts +17 -0
- package/dist/client/rpc-transport-plugin.d.ts.map +1 -0
- package/dist/client/rpc-transport-plugin.js +69 -0
- package/dist/client/rpc-transport-plugin.js.map +1 -0
- package/dist/client/tools.d.ts +69 -0
- package/dist/client/tools.d.ts.map +1 -0
- package/dist/client/tools.js +122 -0
- package/dist/client/tools.js.map +1 -0
- package/dist/client/transport-plugin.d.ts +62 -0
- package/dist/client/transport-plugin.d.ts.map +1 -0
- package/dist/client/transport-plugin.js +40 -0
- package/dist/client/transport-plugin.js.map +1 -0
- package/dist/client-entry.d.ts +25 -0
- package/dist/client-entry.d.ts.map +1 -0
- package/dist/client-entry.js +25 -0
- package/dist/client-entry.js.map +1 -0
- package/dist/client-server-entry.d.ts +13 -0
- package/dist/client-server-entry.d.ts.map +1 -0
- package/dist/client-server-entry.js +13 -0
- package/dist/client-server-entry.js.map +1 -0
- package/dist/client-side-python/runtime.d.ts +102 -0
- package/dist/client-side-python/runtime.d.ts.map +1 -0
- package/dist/client-side-python/runtime.js +595 -0
- package/dist/client-side-python/runtime.js.map +1 -0
- package/dist/client-side-server/bootstrap.d.ts +3 -0
- package/dist/client-side-server/bootstrap.d.ts.map +1 -0
- package/dist/client-side-server/bootstrap.js +20 -0
- package/dist/client-side-server/bootstrap.js.map +1 -0
- package/dist/client-side-server/channel.d.ts +17 -0
- package/dist/client-side-server/channel.d.ts.map +1 -0
- package/dist/client-side-server/channel.js +38 -0
- package/dist/client-side-server/channel.js.map +1 -0
- package/dist/client-side-server/identity.d.ts +116 -0
- package/dist/client-side-server/identity.d.ts.map +1 -0
- package/dist/client-side-server/identity.js +358 -0
- package/dist/client-side-server/identity.js.map +1 -0
- package/dist/client-side-server/mqtt-webrtc.d.ts +77 -0
- package/dist/client-side-server/mqtt-webrtc.d.ts.map +1 -0
- package/dist/client-side-server/mqtt-webrtc.js +575 -0
- package/dist/client-side-server/mqtt-webrtc.js.map +1 -0
- package/dist/client-side-server/protocol.d.ts +49 -0
- package/dist/client-side-server/protocol.d.ts.map +1 -0
- package/dist/client-side-server/protocol.js +13 -0
- package/dist/client-side-server/protocol.js.map +1 -0
- package/dist/client-side-server/runtime.d.ts +57 -0
- package/dist/client-side-server/runtime.d.ts.map +1 -0
- package/dist/client-side-server/runtime.js +188 -0
- package/dist/client-side-server/runtime.js.map +1 -0
- package/dist/client-side-server/server.d.ts +75 -0
- package/dist/client-side-server/server.d.ts.map +1 -0
- package/dist/client-side-server/server.js +380 -0
- package/dist/client-side-server/server.js.map +1 -0
- package/dist/client-side-server/signaling.d.ts +10 -0
- package/dist/client-side-server/signaling.d.ts.map +1 -0
- package/dist/client-side-server/signaling.js +19 -0
- package/dist/client-side-server/signaling.js.map +1 -0
- package/dist/client-side-server/source-analysis.d.ts +29 -0
- package/dist/client-side-server/source-analysis.d.ts.map +1 -0
- package/dist/client-side-server/source-analysis.js +395 -0
- package/dist/client-side-server/source-analysis.js.map +1 -0
- package/dist/generated/python-browser-sources.d.ts +2 -0
- package/dist/generated/python-browser-sources.d.ts.map +1 -0
- package/dist/generated/python-browser-sources.js +13 -0
- package/dist/generated/python-browser-sources.js.map +1 -0
- package/dist/logging.d.ts +9 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +64 -0
- package/dist/logging.js.map +1 -0
- package/dist/python-browser-entry.d.ts +2 -0
- package/dist/python-browser-entry.d.ts.map +1 -0
- package/dist/python-browser-entry.js +2 -0
- package/dist/python-browser-entry.js.map +1 -0
- package/dist/rpc.d.ts +39 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +2 -0
- package/dist/rpc.js.map +1 -0
- package/dist/server/authority-server.d.ts +27 -0
- package/dist/server/authority-server.d.ts.map +1 -0
- package/dist/server/authority-server.js +97 -0
- package/dist/server/authority-server.js.map +1 -0
- package/dist/server/cache/index.d.ts +2 -0
- package/dist/server/cache/index.d.ts.map +1 -0
- package/dist/server/cache/index.js +2 -0
- package/dist/server/cache/index.js.map +1 -0
- package/dist/server/cache/utils.d.ts +30 -0
- package/dist/server/cache/utils.d.ts.map +1 -0
- package/dist/server/cache/utils.js +116 -0
- package/dist/server/cache/utils.js.map +1 -0
- package/dist/server/core.d.ts +43 -0
- package/dist/server/core.d.ts.map +1 -0
- package/dist/server/core.js +215 -0
- package/dist/server/core.js.map +1 -0
- package/dist/server/operation-registry.d.ts +9 -0
- package/dist/server/operation-registry.d.ts.map +1 -0
- package/dist/server/operation-registry.js +16 -0
- package/dist/server/operation-registry.js.map +1 -0
- package/dist/server/param-aliases.d.ts +40 -0
- package/dist/server/param-aliases.d.ts.map +1 -0
- package/dist/server/param-aliases.js +112 -0
- package/dist/server/param-aliases.js.map +1 -0
- package/dist/server/rate-limit/index.d.ts +2 -0
- package/dist/server/rate-limit/index.d.ts.map +1 -0
- package/dist/server/rate-limit/index.js +2 -0
- package/dist/server/rate-limit/index.js.map +1 -0
- package/dist/server/rate-limit/utils.d.ts +27 -0
- package/dist/server/rate-limit/utils.d.ts.map +1 -0
- package/dist/server/rate-limit/utils.js +126 -0
- package/dist/server/rate-limit/utils.js.map +1 -0
- package/dist/server/routing.d.ts +39 -0
- package/dist/server/routing.d.ts.map +1 -0
- package/dist/server/routing.js +70 -0
- package/dist/server/routing.js.map +1 -0
- package/dist/server/token-limit/index.d.ts +2 -0
- package/dist/server/token-limit/index.d.ts.map +1 -0
- package/dist/server/token-limit/index.js +2 -0
- package/dist/server/token-limit/index.js.map +1 -0
- package/dist/server/token-limit/utils.d.ts +44 -0
- package/dist/server/token-limit/utils.d.ts.map +1 -0
- package/dist/server/token-limit/utils.js +260 -0
- package/dist/server/token-limit/utils.js.map +1 -0
- package/dist/server/tools.d.ts +33 -0
- package/dist/server/tools.d.ts.map +1 -0
- package/dist/server/tools.js +160 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/server/transports.d.ts +25 -0
- package/dist/server/transports.d.ts.map +1 -0
- package/dist/server/transports.js +2 -0
- package/dist/server/transports.js.map +1 -0
- package/dist/shared/tools.d.ts +24 -0
- package/dist/shared/tools.d.ts.map +1 -0
- package/dist/shared/tools.js +86 -0
- package/dist/shared/tools.js.map +1 -0
- package/dist/spec/decorators.d.ts +41 -0
- package/dist/spec/decorators.d.ts.map +1 -0
- package/dist/spec/decorators.js +93 -0
- package/dist/spec/decorators.js.map +1 -0
- package/dist/spec/index.d.ts +3 -0
- package/dist/spec/index.d.ts.map +1 -0
- package/dist/spec/index.js +3 -0
- package/dist/spec/index.js.map +1 -0
- package/dist/spec/metadata.d.ts +5 -0
- package/dist/spec/metadata.d.ts.map +1 -0
- package/dist/spec/metadata.js +37 -0
- package/dist/spec/metadata.js.map +1 -0
- package/dist/types/client-route.d.ts +7 -0
- package/dist/types/client-route.d.ts.map +1 -0
- package/dist/types/client-route.js +2 -0
- package/dist/types/client-route.js.map +1 -0
- package/dist/types/client.d.ts +81 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/client.js +14 -0
- package/dist/types/client.js.map +1 -0
- package/dist/types/endpoints.d.ts +76 -0
- package/dist/types/endpoints.d.ts.map +1 -0
- package/dist/types/endpoints.js +2 -0
- package/dist/types/endpoints.js.map +1 -0
- package/dist/types/errors.d.ts +86 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +153 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/http.d.ts +80 -0
- package/dist/types/http.d.ts.map +1 -0
- package/dist/types/http.js +61 -0
- package/dist/types/http.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/openapi.d.ts +220 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +11 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/types/opts.d.ts +46 -0
- package/dist/types/opts.d.ts.map +1 -0
- package/dist/types/opts.js +2 -0
- package/dist/types/opts.js.map +1 -0
- package/dist/types/plugins.d.ts +93 -0
- package/dist/types/plugins.d.ts.map +1 -0
- package/dist/types/plugins.js +5 -0
- package/dist/types/plugins.js.map +1 -0
- package/dist/types/tools.d.ts +52 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +2 -0
- package/dist/types/tools.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { createToolDefinition } from './tools.js';
|
|
2
|
+
import { generateRouteVariants } from './routing.js';
|
|
3
|
+
import { ensureControllerMeta, ensureRouteMeta, getControllerMeta, pendingRoutes, ROUTE_METADATA_KEY } from '../spec/index.js';
|
|
4
|
+
const RESERVED_METHOD_NAMES = ['tools', 'routes', 'endpoints', 'help', 'openapi'];
|
|
5
|
+
export class PLATServerCore {
|
|
6
|
+
options;
|
|
7
|
+
stores;
|
|
8
|
+
constructor(options, stores) {
|
|
9
|
+
this.options = options;
|
|
10
|
+
this.stores = stores;
|
|
11
|
+
}
|
|
12
|
+
registerControllers(...ControllerClasses) {
|
|
13
|
+
const registered = [];
|
|
14
|
+
for (const ControllerClass of ControllerClasses) {
|
|
15
|
+
const meta = getControllerMeta(ControllerClass) ?? ensureControllerMeta(ControllerClass);
|
|
16
|
+
if (!meta.basePath)
|
|
17
|
+
meta.basePath = ControllerClass.name;
|
|
18
|
+
if (!meta.tag)
|
|
19
|
+
meta.tag = meta.basePath || ControllerClass.name;
|
|
20
|
+
const instance = new ControllerClass();
|
|
21
|
+
const controllerTag = meta.tag || meta.basePath || ControllerClass.name;
|
|
22
|
+
const lowerControllerTag = controllerTag.toLowerCase();
|
|
23
|
+
if (RESERVED_METHOD_NAMES.includes(lowerControllerTag)) {
|
|
24
|
+
throw new Error(`Controller '${controllerTag}' uses a reserved plat system name. ` +
|
|
25
|
+
`Reserved names: ${RESERVED_METHOD_NAMES.join(', ')}. ` +
|
|
26
|
+
`Choose a different controller name/tag.`);
|
|
27
|
+
}
|
|
28
|
+
if (this.stores.registeredMethodNames.has(controllerTag)) {
|
|
29
|
+
throw new Error(`Controller '${controllerTag}' conflicts with an existing method name. ` +
|
|
30
|
+
`Controller names and method names must not overlap. ` +
|
|
31
|
+
`Rename either the controller or the method.`);
|
|
32
|
+
}
|
|
33
|
+
this.stores.registeredControllerNames.add(controllerTag);
|
|
34
|
+
this.processPendingRoutes(ControllerClass);
|
|
35
|
+
const freshMeta = getControllerMeta(ControllerClass);
|
|
36
|
+
const routes = this.collectRoutes(ControllerClass, freshMeta);
|
|
37
|
+
for (const [key, route] of routes.entries()) {
|
|
38
|
+
const methodName = String(key);
|
|
39
|
+
this.validateMethodName(methodName, ControllerClass.name);
|
|
40
|
+
if (this.stores.registeredControllerNames.has(methodName)) {
|
|
41
|
+
throw new Error(`Method '${methodName}' in ${ControllerClass.name} conflicts with controller name '${methodName}'. ` +
|
|
42
|
+
`Method names and controller names must not overlap. ` +
|
|
43
|
+
`Rename either the method or the controller.`);
|
|
44
|
+
}
|
|
45
|
+
if (this.stores.registeredMethodNames.has(methodName)) {
|
|
46
|
+
throw new Error(`Duplicate operationId: method "${methodName}" is defined in multiple controllers. ` +
|
|
47
|
+
`In plat, method names must be globally unique across all controllers. ` +
|
|
48
|
+
`Consider renaming one of these methods to have a unique name. ` +
|
|
49
|
+
`Current controller: ${ControllerClass.name}`);
|
|
50
|
+
}
|
|
51
|
+
this.stores.registeredMethodNames.add(methodName);
|
|
52
|
+
const fullPath = '/' + methodName;
|
|
53
|
+
const routeMeta = freshMeta?.routes.get(key);
|
|
54
|
+
this.stores.tools.set(methodName, createToolDefinition({
|
|
55
|
+
name: methodName,
|
|
56
|
+
summary: routeMeta?.summary ?? routeMeta?.opts?.summary,
|
|
57
|
+
description: routeMeta?.description ?? routeMeta?.opts?.description ?? `${route.method.toUpperCase()} ${fullPath}`,
|
|
58
|
+
method: route.method,
|
|
59
|
+
path: fullPath,
|
|
60
|
+
controller: controllerTag,
|
|
61
|
+
tags: [
|
|
62
|
+
controllerTag,
|
|
63
|
+
...(Array.isArray(routeMeta?.opts?.tags) ? routeMeta?.opts?.tags : []),
|
|
64
|
+
].filter((value, index, arr) => Boolean(value) && arr.indexOf(value) === index),
|
|
65
|
+
examples: Array.isArray(routeMeta?.opts?.examples) ? routeMeta?.opts?.examples : undefined,
|
|
66
|
+
hidden: routeMeta?.opts?.hidden === true,
|
|
67
|
+
safe: routeMeta?.opts?.safe ?? ['GET', 'HEAD'].includes(route.method.toUpperCase()),
|
|
68
|
+
idempotent: routeMeta?.opts?.idempotent ?? ['GET', 'HEAD', 'PUT', 'DELETE'].includes(route.method.toUpperCase()),
|
|
69
|
+
longRunning: routeMeta?.opts?.longRunning === true,
|
|
70
|
+
input_schema: routeMeta?.inputSchema ? createToolDefinition(methodName, route.method, fullPath, '', routeMeta.inputSchema).input_schema : undefined,
|
|
71
|
+
response_schema: routeMeta?.outputSchema ? createToolDefinition(methodName, route.method, fullPath, '', undefined, routeMeta.outputSchema).response_schema : undefined,
|
|
72
|
+
}));
|
|
73
|
+
const operation = {
|
|
74
|
+
method: route.method.toUpperCase(),
|
|
75
|
+
path: fullPath,
|
|
76
|
+
methodName,
|
|
77
|
+
boundMethod: instance[methodName].bind(instance),
|
|
78
|
+
controllerTag,
|
|
79
|
+
routeMeta,
|
|
80
|
+
controllerMeta: freshMeta,
|
|
81
|
+
};
|
|
82
|
+
this.stores.operationRegistry.register(operation);
|
|
83
|
+
const routeRecord = {
|
|
84
|
+
method: route.method.toUpperCase(),
|
|
85
|
+
path: fullPath,
|
|
86
|
+
methodName,
|
|
87
|
+
};
|
|
88
|
+
this.stores.routes.push(routeRecord);
|
|
89
|
+
registered.push({
|
|
90
|
+
operation,
|
|
91
|
+
route: routeRecord,
|
|
92
|
+
variants: generateRouteVariants(methodName, route.method)
|
|
93
|
+
.filter((variant) => !(variant.path === fullPath && variant.method === route.method.toUpperCase())),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return registered;
|
|
98
|
+
}
|
|
99
|
+
processPendingRoutes(ControllerClass) {
|
|
100
|
+
if (!pendingRoutes.has(ControllerClass))
|
|
101
|
+
return;
|
|
102
|
+
const routes = pendingRoutes.get(ControllerClass);
|
|
103
|
+
for (const route of routes) {
|
|
104
|
+
const routeMeta = ensureRouteMeta(ControllerClass, route.key);
|
|
105
|
+
routeMeta.method = route.method;
|
|
106
|
+
routeMeta.path = '/' + String(route.key);
|
|
107
|
+
routeMeta.auth = route.opts?.auth;
|
|
108
|
+
routeMeta.rateLimit = route.opts?.rateLimit;
|
|
109
|
+
routeMeta.tokenLimit = route.opts?.tokenLimit;
|
|
110
|
+
routeMeta.cache = route.opts?.cache;
|
|
111
|
+
routeMeta.summary = route.opts?.summary;
|
|
112
|
+
routeMeta.description = route.opts?.description;
|
|
113
|
+
if (route.opts) {
|
|
114
|
+
routeMeta.opts = route.opts;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
pendingRoutes.delete(ControllerClass);
|
|
118
|
+
}
|
|
119
|
+
collectRoutes(ControllerClass, freshMeta) {
|
|
120
|
+
const routes = new Map();
|
|
121
|
+
const undecoratedMode = this.options.undecoratedMode ?? 'POST';
|
|
122
|
+
for (const key of Object.getOwnPropertyNames(ControllerClass.prototype)) {
|
|
123
|
+
if (key === 'constructor')
|
|
124
|
+
continue;
|
|
125
|
+
if (key.startsWith('_'))
|
|
126
|
+
continue;
|
|
127
|
+
const method = ControllerClass.prototype[key];
|
|
128
|
+
if (typeof method !== 'function')
|
|
129
|
+
continue;
|
|
130
|
+
const routeData = method[ROUTE_METADATA_KEY];
|
|
131
|
+
if (routeData) {
|
|
132
|
+
routes.set(key, { method: routeData.httpMethod });
|
|
133
|
+
}
|
|
134
|
+
else if (undecoratedMode !== 'private') {
|
|
135
|
+
routes.set(key, { method: undecoratedMode });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (freshMeta) {
|
|
139
|
+
for (const [key, routeMeta] of freshMeta.routes.entries()) {
|
|
140
|
+
const keyName = String(key);
|
|
141
|
+
const prototypeMethod = ControllerClass.prototype?.[keyName];
|
|
142
|
+
if (typeof prototypeMethod !== 'function' || keyName === 'constructor' || keyName.startsWith('_')) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
const inferredMethod = routeMeta.method ?? (undecoratedMode !== 'private' ? undecoratedMode : undefined);
|
|
146
|
+
if (!inferredMethod)
|
|
147
|
+
continue;
|
|
148
|
+
routes.set(key, { method: inferredMethod });
|
|
149
|
+
if (this.options.validateRouteOpts && routeMeta.opts) {
|
|
150
|
+
const result = this.options.validateRouteOpts(routeMeta.opts, String(key), routeMeta.path);
|
|
151
|
+
if (result && typeof result === 'object' && 'then' in result) {
|
|
152
|
+
// Keep behavior aligned with the current server host.
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return routes;
|
|
158
|
+
}
|
|
159
|
+
extractMethodPrefix(methodName) {
|
|
160
|
+
const standardPrefixes = ['create', 'update', 'delete', 'list', 'find', 'send', 'get', 'do'];
|
|
161
|
+
for (const prefix of standardPrefixes) {
|
|
162
|
+
if (methodName.startsWith(prefix) && methodName.length > prefix.length) {
|
|
163
|
+
const nextChar = methodName.charAt(prefix.length);
|
|
164
|
+
if (nextChar === nextChar.toUpperCase()) {
|
|
165
|
+
return prefix;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (let i = 1; i < methodName.length; i++) {
|
|
170
|
+
const char = methodName.charAt(i);
|
|
171
|
+
if (char === char.toUpperCase() && char !== char.toLowerCase()) {
|
|
172
|
+
return methodName.substring(0, i);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return methodName.length > 0 ? methodName : null;
|
|
176
|
+
}
|
|
177
|
+
validateMethodName(methodName, controllerName) {
|
|
178
|
+
if (!methodName || methodName.length === 0)
|
|
179
|
+
return;
|
|
180
|
+
const firstChar = methodName.charAt(0);
|
|
181
|
+
if (firstChar === firstChar.toUpperCase() && firstChar !== firstChar.toLowerCase()) {
|
|
182
|
+
throw new Error(`Method '${methodName}' in ${controllerName} violates plat naming convention: ` +
|
|
183
|
+
`method names must start with a lowercase letter. ` +
|
|
184
|
+
`Use '${firstChar.toLowerCase()}${methodName.slice(1)}' instead.`);
|
|
185
|
+
}
|
|
186
|
+
if (methodName.includes('_')) {
|
|
187
|
+
const camelCase = methodName.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
|
|
188
|
+
throw new Error(`Method '${methodName}' in ${controllerName} violates plat naming convention: ` +
|
|
189
|
+
`underscores are not allowed. Use camelCase instead. ` +
|
|
190
|
+
`Use '${camelCase}' instead.`);
|
|
191
|
+
}
|
|
192
|
+
if (RESERVED_METHOD_NAMES.includes(methodName.toLowerCase())) {
|
|
193
|
+
throw new Error(`Method '${methodName}' in ${controllerName} uses a reserved plat system name. ` +
|
|
194
|
+
`Reserved names: ${RESERVED_METHOD_NAMES.join(', ')}. ` +
|
|
195
|
+
`Choose a different method name.`);
|
|
196
|
+
}
|
|
197
|
+
if (this.options.allowedMethodPrefixes && this.options.allowedMethodPrefixes !== '*') {
|
|
198
|
+
const prefix = this.extractMethodPrefix(methodName);
|
|
199
|
+
if (prefix && !this.options.allowedMethodPrefixes.includes(prefix)) {
|
|
200
|
+
throw new Error(`Method '${methodName}' in ${controllerName} uses disallowed prefix '${prefix}'. ` +
|
|
201
|
+
`Allowed prefixes: ${this.options.allowedMethodPrefixes.join(', ')}. ` +
|
|
202
|
+
`Rename the method to use an allowed prefix.`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (this.options.disAllowedMethodPrefixes && this.options.disAllowedMethodPrefixes.length > 0) {
|
|
206
|
+
const prefix = this.extractMethodPrefix(methodName);
|
|
207
|
+
if (prefix && this.options.disAllowedMethodPrefixes.includes(prefix)) {
|
|
208
|
+
throw new Error(`Method '${methodName}' in ${controllerName} uses disallowed prefix '${prefix}'. ` +
|
|
209
|
+
`Disallowed prefixes: ${this.options.disAllowedMethodPrefixes.join(', ')}. ` +
|
|
210
|
+
`Rename the method to use a different prefix.`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../typescript/src/server/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PLATServerCallEnvelope, PLATServerResolvedOperation } from './transports';
|
|
2
|
+
export declare class PLATOperationRegistry {
|
|
3
|
+
private operationsById;
|
|
4
|
+
private operationsByRoute;
|
|
5
|
+
register(operation: PLATServerResolvedOperation): void;
|
|
6
|
+
resolve(envelope: Pick<PLATServerCallEnvelope, 'operationId' | 'method' | 'path'>): PLATServerResolvedOperation | undefined;
|
|
7
|
+
list(): PLATServerResolvedOperation[];
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=operation-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-registry.d.ts","sourceRoot":"","sources":["../../../typescript/src/server/operation-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAA;AAEvF,qBAAa,qBAAqB;IAChC,OAAO,CAAC,cAAc,CAAiD;IACvE,OAAO,CAAC,iBAAiB,CAAiD;IAE1E,QAAQ,CAAC,SAAS,EAAE,2BAA2B,GAAG,IAAI;IAKtD,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAC,GAAG,2BAA2B,GAAG,SAAS;IAK3H,IAAI,IAAI,2BAA2B,EAAE;CAGtC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export class PLATOperationRegistry {
|
|
2
|
+
operationsById = new Map();
|
|
3
|
+
operationsByRoute = new Map();
|
|
4
|
+
register(operation) {
|
|
5
|
+
this.operationsById.set(operation.methodName, operation);
|
|
6
|
+
this.operationsByRoute.set(`${operation.method.toUpperCase()} ${operation.path}`, operation);
|
|
7
|
+
}
|
|
8
|
+
resolve(envelope) {
|
|
9
|
+
return (envelope.operationId ? this.operationsById.get(envelope.operationId) : undefined)
|
|
10
|
+
?? this.operationsByRoute.get(`${envelope.method.toUpperCase()} ${envelope.path}`);
|
|
11
|
+
}
|
|
12
|
+
list() {
|
|
13
|
+
return Array.from(this.operationsById.values());
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=operation-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-registry.js","sourceRoot":"","sources":["../../../typescript/src/server/operation-registry.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,qBAAqB;IACxB,cAAc,GAAG,IAAI,GAAG,EAAuC,CAAA;IAC/D,iBAAiB,GAAG,IAAI,GAAG,EAAuC,CAAA;IAE1E,QAAQ,CAAC,SAAsC;QAC7C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;QACxD,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC,CAAA;IAC9F,CAAC;IAED,OAAO,CAAC,QAAyE;QAC/E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;eACpF,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IACtF,CAAC;IAED,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAA;IACjD,CAAC;CACF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter Aliasing
|
|
3
|
+
*
|
|
4
|
+
* Maps common parameter name variants to canonical plat parameter names.
|
|
5
|
+
* This ensures consistency while being resilient to common naming mistakes.
|
|
6
|
+
*
|
|
7
|
+
* Examples:
|
|
8
|
+
* - `query` → `q`
|
|
9
|
+
* - `search` → `q`
|
|
10
|
+
* - `format` → `fmt`
|
|
11
|
+
* - `page` + `pageSize` → `limit` + `offset`
|
|
12
|
+
*/
|
|
13
|
+
export interface ParameterAliases {
|
|
14
|
+
[alias: string]: string | ((value: any, params: Record<string, any>) => void);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Normalize/alias a parameters object
|
|
18
|
+
* Converts common parameter name variants to plat canonical names
|
|
19
|
+
*
|
|
20
|
+
* @param params The input parameters object
|
|
21
|
+
* @param paramCoercions Optional config map of parameter aliases (from PLATServerOptions)
|
|
22
|
+
* @param disAllowedParams Optional list of forbidden parameter names
|
|
23
|
+
* @returns New params object with aliased names resolved
|
|
24
|
+
* @throws Error if a disallowed parameter is found in the input
|
|
25
|
+
*/
|
|
26
|
+
export declare function normalizeParameters(params: Record<string, any>, paramCoercions?: Record<string, string>, disAllowedParams?: string[]): Record<string, any>;
|
|
27
|
+
/**
|
|
28
|
+
* Get all known parameter aliases
|
|
29
|
+
* Useful for documentation and validation
|
|
30
|
+
*/
|
|
31
|
+
export declare function getKnownAliases(): Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Check if a parameter name would be aliased
|
|
34
|
+
*/
|
|
35
|
+
export declare function isAliasedParameter(paramName: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Get canonical name for a parameter
|
|
38
|
+
*/
|
|
39
|
+
export declare function getCanonicalName(paramName: string): string | null;
|
|
40
|
+
//# sourceMappingURL=param-aliases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"param-aliases.d.ts","sourceRoot":"","sources":["../../../typescript/src/server/param-aliases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC,CAAA;CAC9E;AAeD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACvC,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAiDrB;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAcxD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUjE"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter Aliasing
|
|
3
|
+
*
|
|
4
|
+
* Maps common parameter name variants to canonical plat parameter names.
|
|
5
|
+
* This ensures consistency while being resilient to common naming mistakes.
|
|
6
|
+
*
|
|
7
|
+
* Examples:
|
|
8
|
+
* - `query` → `q`
|
|
9
|
+
* - `search` → `q`
|
|
10
|
+
* - `format` → `fmt`
|
|
11
|
+
* - `page` + `pageSize` → `limit` + `offset`
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Map of parameter aliases to canonical names
|
|
15
|
+
* Value can be:
|
|
16
|
+
* - string: direct alias (query → q)
|
|
17
|
+
* - function: complex transformation (page/pageSize → limit/offset)
|
|
18
|
+
*/
|
|
19
|
+
const PARAMETER_ALIASES = {
|
|
20
|
+
query: 'q',
|
|
21
|
+
search: 'q',
|
|
22
|
+
format: 'fmt',
|
|
23
|
+
// Complex transformations are handled separately
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Normalize/alias a parameters object
|
|
27
|
+
* Converts common parameter name variants to plat canonical names
|
|
28
|
+
*
|
|
29
|
+
* @param params The input parameters object
|
|
30
|
+
* @param paramCoercions Optional config map of parameter aliases (from PLATServerOptions)
|
|
31
|
+
* @param disAllowedParams Optional list of forbidden parameter names
|
|
32
|
+
* @returns New params object with aliased names resolved
|
|
33
|
+
* @throws Error if a disallowed parameter is found in the input
|
|
34
|
+
*/
|
|
35
|
+
export function normalizeParameters(params, paramCoercions, disAllowedParams) {
|
|
36
|
+
if (!params || typeof params !== 'object') {
|
|
37
|
+
return params;
|
|
38
|
+
}
|
|
39
|
+
// Check for disallowed parameters first
|
|
40
|
+
if (disAllowedParams && disAllowedParams.length > 0) {
|
|
41
|
+
for (const paramName of Object.keys(params)) {
|
|
42
|
+
if (disAllowedParams.includes(paramName)) {
|
|
43
|
+
throw new Error(`Parameter '${paramName}' is disallowed in this API. ` +
|
|
44
|
+
`Use '${getCanonicalName(paramName) || 'a different parameter'}' instead.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const normalized = { ...params };
|
|
49
|
+
const aliases = paramCoercions || PARAMETER_ALIASES;
|
|
50
|
+
// Apply simple aliases
|
|
51
|
+
for (const [alias, canonical] of Object.entries(aliases)) {
|
|
52
|
+
if (typeof canonical === 'string' && alias in normalized && canonical) {
|
|
53
|
+
if (!(canonical in normalized)) {
|
|
54
|
+
normalized[canonical] = normalized[alias];
|
|
55
|
+
}
|
|
56
|
+
delete normalized[alias];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Handle page/pageSize → limit/offset conversion
|
|
60
|
+
if ('page' in normalized || 'pageSize' in normalized) {
|
|
61
|
+
const page = normalized.page ?? 1;
|
|
62
|
+
const pageSize = normalized.pageSize ?? 10;
|
|
63
|
+
// Only apply if limit/offset aren't already set
|
|
64
|
+
if (!('limit' in normalized)) {
|
|
65
|
+
normalized.limit = pageSize;
|
|
66
|
+
}
|
|
67
|
+
if (!('offset' in normalized)) {
|
|
68
|
+
normalized.offset = (page - 1) * pageSize;
|
|
69
|
+
}
|
|
70
|
+
// Remove the original page/pageSize
|
|
71
|
+
delete normalized.page;
|
|
72
|
+
delete normalized.pageSize;
|
|
73
|
+
}
|
|
74
|
+
return normalized;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get all known parameter aliases
|
|
78
|
+
* Useful for documentation and validation
|
|
79
|
+
*/
|
|
80
|
+
export function getKnownAliases() {
|
|
81
|
+
const aliases = {};
|
|
82
|
+
for (const [alias, canonical] of Object.entries(PARAMETER_ALIASES)) {
|
|
83
|
+
if (typeof canonical === 'string') {
|
|
84
|
+
aliases[alias] = canonical;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Add page/pageSize special handling
|
|
88
|
+
aliases['page'] = 'offset (calculated as (page-1)*pageSize)';
|
|
89
|
+
aliases['pageSize'] = 'limit';
|
|
90
|
+
return aliases;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if a parameter name would be aliased
|
|
94
|
+
*/
|
|
95
|
+
export function isAliasedParameter(paramName) {
|
|
96
|
+
return paramName in PARAMETER_ALIASES || paramName === 'page' || paramName === 'pageSize';
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get canonical name for a parameter
|
|
100
|
+
*/
|
|
101
|
+
export function getCanonicalName(paramName) {
|
|
102
|
+
if (paramName === 'page')
|
|
103
|
+
return 'offset';
|
|
104
|
+
if (paramName === 'pageSize')
|
|
105
|
+
return 'limit';
|
|
106
|
+
const alias = PARAMETER_ALIASES[paramName];
|
|
107
|
+
if (typeof alias === 'string') {
|
|
108
|
+
return alias;
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=param-aliases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"param-aliases.js","sourceRoot":"","sources":["../../../typescript/src/server/param-aliases.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../typescript/src/server/rate-limit/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../typescript/src/server/rate-limit/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RateLimitController, RateLimitMeta, RateLimitConfigs, ResolvedRateLimitEntry } from '../../types/plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve rate limit key with substitutions:
|
|
4
|
+
* - :route → methodName
|
|
5
|
+
* - :parent → basePath
|
|
6
|
+
* - :user:{field} → user[field] from auth context (e.g., :user:plan, :user:id)
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveRateLimitKey(raw: string, methodName: string, basePath: string, user?: any): string;
|
|
9
|
+
/**
|
|
10
|
+
* Create an in-memory rate limit controller with token-bucket algorithm
|
|
11
|
+
* Lazy fills bucket on each access
|
|
12
|
+
*/
|
|
13
|
+
export declare function createInMemoryRateLimit(): RateLimitController;
|
|
14
|
+
/**
|
|
15
|
+
* Pre-handler: normalize → array, resolve keys, lookup config,
|
|
16
|
+
* call controller.deduct(), return resolved entries + remaining balances
|
|
17
|
+
*/
|
|
18
|
+
export declare function applyRateLimitCheck(meta: RateLimitMeta | undefined, controller: RateLimitController, configs: RateLimitConfigs, methodName: string, basePath: string, user?: any): Promise<{
|
|
19
|
+
entries: ResolvedRateLimitEntry[];
|
|
20
|
+
remainingBalances: number[];
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Post-handler: refund if statusCode in refundedStatusCodes,
|
|
24
|
+
* OR if refundSuccessful && 2xx
|
|
25
|
+
*/
|
|
26
|
+
export declare function applyRateLimitRefund(entries: ResolvedRateLimitEntry[], controller: RateLimitController, statusCode: number): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../typescript/src/server/rate-limit/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,mBAAmB,EAEnB,aAAa,EACb,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,qBAAqB,CAAA;AAM5B;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,GAAG,GACT,MAAM,CAoBR;AAWD;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,mBAAmB,CAoE7D;AAMD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,UAAU,EAAE,mBAAmB,EAC/B,OAAO,EAAE,gBAAgB,EACzB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,GAAG,GACT,OAAO,CAAC;IAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA6B7E;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,sBAAsB,EAAE,EACjC,UAAU,EAAE,mBAAmB,EAC/B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { HttpError } from "../../types/index.js";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// KEY SUBSTITUTION
|
|
4
|
+
// ============================================================================
|
|
5
|
+
/**
|
|
6
|
+
* Resolve rate limit key with substitutions:
|
|
7
|
+
* - :route → methodName
|
|
8
|
+
* - :parent → basePath
|
|
9
|
+
* - :user:{field} → user[field] from auth context (e.g., :user:plan, :user:id)
|
|
10
|
+
*/
|
|
11
|
+
export function resolveRateLimitKey(raw, methodName, basePath, user) {
|
|
12
|
+
let key = raw
|
|
13
|
+
.replace(':route', methodName)
|
|
14
|
+
.replace(':parent', basePath);
|
|
15
|
+
// Replace :user:{field} with user property
|
|
16
|
+
if (user) {
|
|
17
|
+
const userMatches = key.match(/:user:(\w+)/g);
|
|
18
|
+
if (userMatches) {
|
|
19
|
+
for (const match of userMatches) {
|
|
20
|
+
const field = match.slice(6); // Remove ':user:'
|
|
21
|
+
const value = user[field];
|
|
22
|
+
if (value !== undefined) {
|
|
23
|
+
key = key.replace(match, String(value));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return key;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create an in-memory rate limit controller with token-bucket algorithm
|
|
32
|
+
* Lazy fills bucket on each access
|
|
33
|
+
*/
|
|
34
|
+
export function createInMemoryRateLimit() {
|
|
35
|
+
const buckets = new Map();
|
|
36
|
+
function refillBucket(key, config) {
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
let bucket = buckets.get(key);
|
|
39
|
+
if (!bucket) {
|
|
40
|
+
bucket = { balance: config.maxBalance, lastRefillMs: now };
|
|
41
|
+
buckets.set(key, bucket);
|
|
42
|
+
return bucket.balance;
|
|
43
|
+
}
|
|
44
|
+
const elapsedMs = now - bucket.lastRefillMs;
|
|
45
|
+
const intervalsElapsed = Math.floor(elapsedMs / config.fillInterval);
|
|
46
|
+
if (intervalsElapsed > 0) {
|
|
47
|
+
const tokensGenerated = intervalsElapsed * config.fillAmount;
|
|
48
|
+
bucket.balance = Math.min(config.maxBalance, bucket.balance + tokensGenerated);
|
|
49
|
+
bucket.lastRefillMs = now - (elapsedMs % config.fillInterval);
|
|
50
|
+
}
|
|
51
|
+
return bucket.balance;
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
check(key, config) {
|
|
55
|
+
const balance = refillBucket(key, config);
|
|
56
|
+
return balance;
|
|
57
|
+
},
|
|
58
|
+
deduct(key, cost, config) {
|
|
59
|
+
const balance = refillBucket(key, config);
|
|
60
|
+
const minBalance = config.minBalance ?? 0;
|
|
61
|
+
const newBalance = balance - cost;
|
|
62
|
+
if (newBalance < minBalance) {
|
|
63
|
+
const deficit = minBalance - newBalance;
|
|
64
|
+
const intervalsNeeded = Math.ceil(deficit / config.fillAmount);
|
|
65
|
+
const retryAfterMs = intervalsNeeded * config.fillInterval;
|
|
66
|
+
throw new HttpError(429, 'Rate limit exceeded', { retryAfterMs });
|
|
67
|
+
}
|
|
68
|
+
const bucket = buckets.get(key);
|
|
69
|
+
bucket.balance = newBalance;
|
|
70
|
+
return newBalance;
|
|
71
|
+
},
|
|
72
|
+
refund(key, cost, config) {
|
|
73
|
+
let bucket = buckets.get(key);
|
|
74
|
+
if (!bucket) {
|
|
75
|
+
bucket = { balance: Math.min(config.maxBalance, cost), lastRefillMs: Date.now() };
|
|
76
|
+
buckets.set(key, bucket);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
bucket.balance = Math.min(config.maxBalance, bucket.balance + cost);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// ============================================================================
|
|
85
|
+
// PIPELINE HELPERS
|
|
86
|
+
// ============================================================================
|
|
87
|
+
/**
|
|
88
|
+
* Pre-handler: normalize → array, resolve keys, lookup config,
|
|
89
|
+
* call controller.deduct(), return resolved entries + remaining balances
|
|
90
|
+
*/
|
|
91
|
+
export async function applyRateLimitCheck(meta, controller, configs, methodName, basePath, user) {
|
|
92
|
+
if (!meta) {
|
|
93
|
+
return { entries: [], remainingBalances: [] };
|
|
94
|
+
}
|
|
95
|
+
const entries = Array.isArray(meta) ? meta : [meta];
|
|
96
|
+
const resolved = [];
|
|
97
|
+
const remainingBalances = [];
|
|
98
|
+
for (const entry of entries) {
|
|
99
|
+
const rawKey = entry.key ?? ':route';
|
|
100
|
+
const key = resolveRateLimitKey(rawKey, methodName, basePath, user);
|
|
101
|
+
const cost = entry.cost ?? 1;
|
|
102
|
+
const config = entry.config ?? configs[key];
|
|
103
|
+
if (!config) {
|
|
104
|
+
throw new Error(`Rate limit config not found for key "${key}". ` +
|
|
105
|
+
`Define it in server.rateLimit.configs or inline in route metadata.`);
|
|
106
|
+
}
|
|
107
|
+
const remaining = await controller.deduct(key, cost, config);
|
|
108
|
+
resolved.push({ key, cost, config });
|
|
109
|
+
remainingBalances.push(remaining);
|
|
110
|
+
}
|
|
111
|
+
return { entries: resolved, remainingBalances };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Post-handler: refund if statusCode in refundedStatusCodes,
|
|
115
|
+
* OR if refundSuccessful && 2xx
|
|
116
|
+
*/
|
|
117
|
+
export async function applyRateLimitRefund(entries, controller, statusCode) {
|
|
118
|
+
for (const entry of entries) {
|
|
119
|
+
const shouldRefund = (entry.config.refundedStatusCodes?.includes(statusCode)) ||
|
|
120
|
+
(entry.config.refundSuccessful && statusCode >= 200 && statusCode < 300);
|
|
121
|
+
if (shouldRefund) {
|
|
122
|
+
await controller.refund(entry.key, entry.cost, entry.config);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../typescript/src/server/rate-limit/utils.ts"],"names":[],"mappings":"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"}
|