@morojs/moro 1.6.6 → 1.6.8
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 +20 -4
- package/dist/core/auth/morojs-adapter.js +17 -14
- package/dist/core/auth/morojs-adapter.js.map +1 -1
- package/dist/core/config/config-sources.js +44 -0
- package/dist/core/config/config-sources.js.map +1 -1
- package/dist/core/database/adapters/drizzle.js +5 -5
- package/dist/core/database/adapters/drizzle.js.map +1 -1
- package/dist/core/database/adapters/mongodb.js +5 -1
- package/dist/core/database/adapters/mongodb.js.map +1 -1
- package/dist/core/database/adapters/mysql.js +5 -1
- package/dist/core/database/adapters/mysql.js.map +1 -1
- package/dist/core/database/adapters/postgresql.js +1 -1
- package/dist/core/database/adapters/postgresql.js.map +1 -1
- package/dist/core/database/adapters/redis.js +2 -2
- package/dist/core/database/adapters/redis.js.map +1 -1
- package/dist/core/database/adapters/sqlite.js +5 -1
- package/dist/core/database/adapters/sqlite.js.map +1 -1
- package/dist/core/docs/index.js.map +1 -1
- package/dist/core/docs/simple-docs.js +2 -1
- package/dist/core/docs/simple-docs.js.map +1 -1
- package/dist/core/docs/swagger-ui.js +1 -0
- package/dist/core/docs/swagger-ui.js.map +1 -1
- package/dist/core/docs/zod-to-openapi.js +4 -0
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/events/event-bus.d.ts +1 -1
- package/dist/core/events/event-bus.js +1 -0
- package/dist/core/events/event-bus.js.map +1 -1
- package/dist/core/framework.d.ts +1 -1
- package/dist/core/framework.js +3 -1
- package/dist/core/framework.js.map +1 -1
- package/dist/core/graphql/adapter.d.ts +73 -0
- package/dist/core/graphql/adapter.js +2 -0
- package/dist/core/graphql/adapter.js.map +1 -0
- package/dist/core/graphql/adapters/graphql-js-adapter.d.ts +26 -0
- package/dist/core/graphql/adapters/graphql-js-adapter.js +229 -0
- package/dist/core/graphql/adapters/graphql-js-adapter.js.map +1 -0
- package/dist/core/graphql/core.d.ts +60 -0
- package/dist/core/graphql/core.js +165 -0
- package/dist/core/graphql/core.js.map +1 -0
- package/dist/core/graphql/index.d.ts +4 -0
- package/dist/core/graphql/index.js +4 -0
- package/dist/core/graphql/index.js.map +1 -0
- package/dist/core/graphql/loader.d.ts +9 -0
- package/dist/core/graphql/loader.js +32 -0
- package/dist/core/graphql/loader.js.map +1 -0
- package/dist/core/graphql/types.d.ts +211 -0
- package/dist/core/graphql/types.js +2 -0
- package/dist/core/graphql/types.js.map +1 -0
- package/dist/core/http/http-server.js +31 -9
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/utils/uws-worker-clustering.d.ts +28 -0
- package/dist/core/http/utils/uws-worker-clustering.js +313 -0
- package/dist/core/http/utils/uws-worker-clustering.js.map +1 -0
- package/dist/core/http/uws-http-server.d.ts +3 -1
- package/dist/core/http/uws-http-server.js +37 -8
- package/dist/core/http/uws-http-server.js.map +1 -1
- package/dist/core/jobs/cron-parser.d.ts +62 -0
- package/dist/core/jobs/cron-parser.js +239 -0
- package/dist/core/jobs/cron-parser.js.map +1 -0
- package/dist/core/jobs/index.d.ts +12 -0
- package/dist/core/jobs/index.js +9 -0
- package/dist/core/jobs/index.js.map +1 -0
- package/dist/core/jobs/job-executor.d.ts +134 -0
- package/dist/core/jobs/job-executor.js +413 -0
- package/dist/core/jobs/job-executor.js.map +1 -0
- package/dist/core/jobs/job-scheduler.d.ts +214 -0
- package/dist/core/jobs/job-scheduler.js +551 -0
- package/dist/core/jobs/job-scheduler.js.map +1 -0
- package/dist/core/jobs/job-state-manager.d.ts +158 -0
- package/dist/core/jobs/job-state-manager.js +444 -0
- package/dist/core/jobs/job-state-manager.js.map +1 -0
- package/dist/core/jobs/leader-election.d.ts +124 -0
- package/dist/core/jobs/leader-election.js +481 -0
- package/dist/core/jobs/leader-election.js.map +1 -0
- package/dist/core/jobs/types.d.ts +151 -0
- package/dist/core/jobs/types.js +4 -0
- package/dist/core/jobs/types.js.map +1 -0
- package/dist/core/jobs/utils.d.ts +95 -0
- package/dist/core/jobs/utils.js +258 -0
- package/dist/core/jobs/utils.js.map +1 -0
- package/dist/core/logger/filters.js +2 -0
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/logger.js +7 -3
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/logger/outputs.js +2 -0
- package/dist/core/logger/outputs.js.map +1 -1
- package/dist/core/middleware/built-in/auth/helpers.js +1 -1
- package/dist/core/middleware/built-in/auth/helpers.js.map +1 -1
- package/dist/core/middleware/built-in/auth/jwt-helpers.js +1 -1
- package/dist/core/middleware/built-in/auth/jwt-helpers.js.map +1 -1
- package/dist/core/middleware/built-in/auth/providers.js +1 -1
- package/dist/core/middleware/built-in/auth/providers.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/file.js +3 -3
- package/dist/core/middleware/built-in/cache/adapters/cache/file.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/memory.js +1 -0
- package/dist/core/middleware/built-in/cache/adapters/cache/memory.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/redis.js +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/redis.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/cdn/azure.d.ts +8 -0
- package/dist/core/middleware/built-in/cdn/adapters/cdn/azure.js +100 -7
- package/dist/core/middleware/built-in/cdn/adapters/cdn/azure.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudflare.d.ts +6 -0
- package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudflare.js +97 -13
- package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudflare.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudfront.js +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudfront.js.map +1 -1
- package/dist/core/middleware/built-in/cookie/hook.d.ts +1 -1
- package/dist/core/middleware/built-in/cookie/hook.js +2 -2
- package/dist/core/middleware/built-in/cookie/hook.js.map +1 -1
- package/dist/core/middleware/built-in/csrf/core.js +1 -0
- package/dist/core/middleware/built-in/csrf/core.js.map +1 -1
- package/dist/core/middleware/built-in/graphql/core.d.ts +11 -0
- package/dist/core/middleware/built-in/graphql/core.js +24 -0
- package/dist/core/middleware/built-in/graphql/core.js.map +1 -0
- package/dist/core/middleware/built-in/graphql/helpers.d.ts +69 -0
- package/dist/core/middleware/built-in/graphql/helpers.js +187 -0
- package/dist/core/middleware/built-in/graphql/helpers.js.map +1 -0
- package/dist/core/middleware/built-in/graphql/hook.d.ts +7 -0
- package/dist/core/middleware/built-in/graphql/hook.js +78 -0
- package/dist/core/middleware/built-in/graphql/hook.js.map +1 -0
- package/dist/core/middleware/built-in/graphql/index.d.ts +5 -0
- package/dist/core/middleware/built-in/graphql/index.js +5 -0
- package/dist/core/middleware/built-in/graphql/index.js.map +1 -0
- package/dist/core/middleware/built-in/graphql/middleware.d.ts +7 -0
- package/dist/core/middleware/built-in/graphql/middleware.js +54 -0
- package/dist/core/middleware/built-in/graphql/middleware.js.map +1 -0
- package/dist/core/middleware/built-in/graphql/subscriptions.d.ts +20 -0
- package/dist/core/middleware/built-in/graphql/subscriptions.js +37 -0
- package/dist/core/middleware/built-in/graphql/subscriptions.js.map +1 -0
- package/dist/core/middleware/built-in/index.d.ts +2 -1
- package/dist/core/middleware/built-in/index.js +3 -0
- package/dist/core/middleware/built-in/index.js.map +1 -1
- package/dist/core/middleware/built-in/validation/core.js +4 -2
- package/dist/core/middleware/built-in/validation/core.js.map +1 -1
- package/dist/core/middleware/index.js +1 -0
- package/dist/core/middleware/index.js.map +1 -1
- package/dist/core/modules/auto-discovery.js +5 -4
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/adapters/socketio-adapter.js +1 -1
- package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
- package/dist/core/networking/adapters/uws-adapter.js +7 -2
- package/dist/core/networking/adapters/uws-adapter.js.map +1 -1
- package/dist/core/networking/adapters/ws-adapter.js +5 -2
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
- package/dist/core/networking/websocket-manager.js +2 -0
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/pooling/object-pool-manager.js +3 -0
- package/dist/core/pooling/object-pool-manager.js.map +1 -1
- package/dist/core/routing/app-integration.d.ts +3 -3
- package/dist/core/routing/app-integration.js +1 -1
- package/dist/core/routing/app-integration.js.map +1 -1
- package/dist/core/routing/index.d.ts +1 -1
- package/dist/core/routing/index.js +1 -1
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/runtime/base-adapter.js +3 -3
- package/dist/core/runtime/base-adapter.js.map +1 -1
- package/dist/core/runtime/cloudflare-workers-adapter.js +1 -1
- package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
- package/dist/core/runtime/node-adapter.d.ts +1 -1
- package/dist/core/runtime/node-adapter.js +7 -4
- package/dist/core/runtime/node-adapter.js.map +1 -1
- package/dist/core/runtime/vercel-edge-adapter.js +1 -0
- package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
- package/dist/core/utilities/circuit-breaker.d.ts +9 -2
- package/dist/core/utilities/circuit-breaker.js +32 -3
- package/dist/core/utilities/circuit-breaker.js.map +1 -1
- package/dist/core/utilities/container.js +6 -0
- package/dist/core/utilities/container.js.map +1 -1
- package/dist/core/utilities/hooks.js +4 -0
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/core/validation/index.js +6 -1
- package/dist/core/validation/index.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/moro.d.ts +154 -1
- package/dist/moro.js +588 -11
- package/dist/moro.js.map +1 -1
- package/dist/types/config.d.ts +28 -0
- package/dist/types/core.d.ts +1 -0
- package/dist/types/events.d.ts +1 -1
- package/dist/types/events.js +1 -0
- package/dist/types/events.js.map +1 -1
- package/dist/types/module.d.ts +2 -2
- package/package.json +21 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// GraphQL Core - Adapter-based GraphQL system
|
|
2
|
+
import { createFrameworkLogger } from '../logger/index.js';
|
|
3
|
+
import { GraphQLJsAdapter } from './adapters/graphql-js-adapter.js';
|
|
4
|
+
const logger = createFrameworkLogger('GraphQL');
|
|
5
|
+
/**
|
|
6
|
+
* GraphQL Core - Manages GraphQL adapter and handles HTTP requests
|
|
7
|
+
*/
|
|
8
|
+
export class GraphQLCore {
|
|
9
|
+
adapter;
|
|
10
|
+
options;
|
|
11
|
+
contextFactory;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.options = options;
|
|
14
|
+
this.contextFactory = options.context;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Initialize GraphQL system with adapter
|
|
18
|
+
*/
|
|
19
|
+
async initialize() {
|
|
20
|
+
logger.info('Initializing GraphQL system', 'Initialization');
|
|
21
|
+
// Create adapter (default to GraphQL.js)
|
|
22
|
+
this.adapter = this.options.adapter || new GraphQLJsAdapter();
|
|
23
|
+
// Initialize adapter
|
|
24
|
+
await this.adapter.initialize(this.options);
|
|
25
|
+
logger.info('GraphQL system initialized successfully', 'Initialization');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Handle HTTP request for GraphQL endpoint
|
|
29
|
+
*/
|
|
30
|
+
async handleRequest(req, res) {
|
|
31
|
+
// Parse request
|
|
32
|
+
const graphqlRequest = await this.parseRequest(req);
|
|
33
|
+
if (!graphqlRequest) {
|
|
34
|
+
res.status(400).json({ errors: [{ message: 'Invalid GraphQL request' }] });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Build context
|
|
38
|
+
const baseContext = {
|
|
39
|
+
request: req,
|
|
40
|
+
response: res,
|
|
41
|
+
};
|
|
42
|
+
const context = this.contextFactory ? await this.contextFactory(req, res) : baseContext;
|
|
43
|
+
// Merge contexts
|
|
44
|
+
graphqlRequest.context = { ...baseContext, ...context };
|
|
45
|
+
// Check introspection
|
|
46
|
+
if (this.options.enableIntrospection === false &&
|
|
47
|
+
this.isIntrospectionQuery(graphqlRequest.query)) {
|
|
48
|
+
res.status(400).json({
|
|
49
|
+
errors: [{ message: 'GraphQL introspection is disabled' }],
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Execute query
|
|
54
|
+
const result = await this.adapter.execute(graphqlRequest);
|
|
55
|
+
// Send response
|
|
56
|
+
res.status(200).json(result);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get GraphQL Playground HTML
|
|
60
|
+
*/
|
|
61
|
+
getPlaygroundHTML() {
|
|
62
|
+
const path = this.options.path || '/graphql';
|
|
63
|
+
return `
|
|
64
|
+
<!DOCTYPE html>
|
|
65
|
+
<html>
|
|
66
|
+
<head>
|
|
67
|
+
<meta charset="utf-8">
|
|
68
|
+
<title>GraphQL Playground</title>
|
|
69
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
70
|
+
<link rel="stylesheet" href="https://unpkg.com/graphiql@2/graphiql.min.css" />
|
|
71
|
+
</head>
|
|
72
|
+
<body style="margin: 0;">
|
|
73
|
+
<div id="graphiql" style="height: 100vh;"></div>
|
|
74
|
+
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
|
75
|
+
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
|
76
|
+
<script crossorigin src="https://unpkg.com/graphiql@2/graphiql.min.js"></script>
|
|
77
|
+
<script>
|
|
78
|
+
const fetcher = GraphiQL.createFetcher({ url: '${path}' });
|
|
79
|
+
const root = ReactDOM.createRoot(document.getElementById('graphiql'));
|
|
80
|
+
root.render(React.createElement(GraphiQL, { fetcher: fetcher }));
|
|
81
|
+
</script>
|
|
82
|
+
</body>
|
|
83
|
+
</html>
|
|
84
|
+
`.trim();
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get schema introspection
|
|
88
|
+
*/
|
|
89
|
+
getIntrospection() {
|
|
90
|
+
return this.adapter.getIntrospection();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get schema SDL
|
|
94
|
+
*/
|
|
95
|
+
getSchemaSDL() {
|
|
96
|
+
return this.adapter.getSchemaSDL();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get schema
|
|
100
|
+
*/
|
|
101
|
+
getSchema() {
|
|
102
|
+
return this.adapter.getSchema();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get adapter
|
|
106
|
+
*/
|
|
107
|
+
getAdapter() {
|
|
108
|
+
return this.adapter;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get statistics
|
|
112
|
+
*/
|
|
113
|
+
getStats() {
|
|
114
|
+
return this.adapter.getStats();
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Cleanup
|
|
118
|
+
*/
|
|
119
|
+
async cleanup() {
|
|
120
|
+
await this.adapter.cleanup();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Parse GraphQL request from HTTP request
|
|
124
|
+
*/
|
|
125
|
+
async parseRequest(req) {
|
|
126
|
+
if (req.method === 'GET') {
|
|
127
|
+
const query = req.query?.query;
|
|
128
|
+
const variables = req.query?.variables;
|
|
129
|
+
const operationName = req.query?.operationName;
|
|
130
|
+
if (!query)
|
|
131
|
+
return null;
|
|
132
|
+
return {
|
|
133
|
+
query,
|
|
134
|
+
variables: variables ? JSON.parse(variables) : undefined,
|
|
135
|
+
operationName,
|
|
136
|
+
context: {},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (req.method === 'POST') {
|
|
140
|
+
const body = req.body;
|
|
141
|
+
if (!body || !body.query)
|
|
142
|
+
return null;
|
|
143
|
+
return {
|
|
144
|
+
query: body.query,
|
|
145
|
+
variables: body.variables,
|
|
146
|
+
operationName: body.operationName,
|
|
147
|
+
context: {},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if query is introspection
|
|
154
|
+
*/
|
|
155
|
+
isIntrospectionQuery(query) {
|
|
156
|
+
return query.includes('__schema') || query.includes('__type');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Create GraphQL core instance
|
|
161
|
+
*/
|
|
162
|
+
export function createGraphQLCore(options) {
|
|
163
|
+
return new GraphQLCore(options);
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/core/graphql/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/graphql/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamically load graphql package from user's node_modules
|
|
3
|
+
* This ensures graphql is only required when actually used
|
|
4
|
+
*/
|
|
5
|
+
export declare function loadGraphQL(): Promise<any>;
|
|
6
|
+
/**
|
|
7
|
+
* Get cached graphql module (must call loadGraphQL first)
|
|
8
|
+
*/
|
|
9
|
+
export declare function getGraphQL(): any;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// GraphQL Dynamic Loader - Lazy loads graphql package
|
|
2
|
+
import { resolveUserPackage } from '../utilities/package-utils.js';
|
|
3
|
+
let graphqlModule = null;
|
|
4
|
+
/**
|
|
5
|
+
* Dynamically load graphql package from user's node_modules
|
|
6
|
+
* This ensures graphql is only required when actually used
|
|
7
|
+
*/
|
|
8
|
+
export async function loadGraphQL() {
|
|
9
|
+
if (graphqlModule) {
|
|
10
|
+
return graphqlModule;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const graphqlPath = resolveUserPackage('graphql');
|
|
14
|
+
graphqlModule = await import(graphqlPath);
|
|
15
|
+
return graphqlModule;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Error('GraphQL package not found. Install it with: npm install graphql\n' +
|
|
19
|
+
'For TypeScript-first GraphQL: npm install @pothos/core\n' +
|
|
20
|
+
'For performance boost: npm install graphql-jit');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get cached graphql module (must call loadGraphQL first)
|
|
25
|
+
*/
|
|
26
|
+
export function getGraphQL() {
|
|
27
|
+
if (!graphqlModule) {
|
|
28
|
+
throw new Error('GraphQL not loaded. Call loadGraphQL() first.');
|
|
29
|
+
}
|
|
30
|
+
return graphqlModule;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/graphql/loader.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,IAAI,aAAa,GAAQ,IAAI,CAAC;AAE9B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAClD,aAAa,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QAC1C,OAAO,aAAa,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,mEAAmE;YACjE,0DAA0D;YAC1D,gDAAgD,CACnD,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import type { HttpRequest, HttpResponse } from '../../types/http.js';
|
|
2
|
+
import type { GraphQLSchema, GraphQLFieldResolver, GraphQLTypeResolver, GraphQLError } from 'graphql';
|
|
3
|
+
/**
|
|
4
|
+
* GraphQL context that's passed to all resolvers
|
|
5
|
+
*/
|
|
6
|
+
export interface GraphQLContext {
|
|
7
|
+
request: HttpRequest;
|
|
8
|
+
response: HttpResponse;
|
|
9
|
+
user?: any;
|
|
10
|
+
auth?: any;
|
|
11
|
+
session?: any;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* GraphQL resolver function signature
|
|
16
|
+
*/
|
|
17
|
+
export type GraphQLResolver<TSource = any, TArgs = any, TContext = GraphQLContext, TResult = any> = GraphQLFieldResolver<TSource, TContext, TArgs, TResult>;
|
|
18
|
+
/**
|
|
19
|
+
* GraphQL subscription resolver
|
|
20
|
+
*/
|
|
21
|
+
export interface GraphQLSubscriptionResolver<TSource = any, TArgs = any, TContext = GraphQLContext> {
|
|
22
|
+
subscribe: GraphQLFieldResolver<TSource, TContext, TArgs>;
|
|
23
|
+
resolve?: GraphQLFieldResolver<TSource, TContext, TArgs>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* GraphQL schema builder options
|
|
27
|
+
*/
|
|
28
|
+
export interface GraphQLSchemaBuilderOptions {
|
|
29
|
+
typeDefs?: string | string[];
|
|
30
|
+
resolvers?: GraphQLResolvers;
|
|
31
|
+
schema?: GraphQLSchema;
|
|
32
|
+
context?: (req: HttpRequest, res: HttpResponse) => GraphQLContext | Promise<GraphQLContext>;
|
|
33
|
+
formatError?: (error: GraphQLError) => any;
|
|
34
|
+
validationRules?: any[];
|
|
35
|
+
extensions?: any[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* GraphQL resolvers map
|
|
39
|
+
*/
|
|
40
|
+
export interface GraphQLResolvers {
|
|
41
|
+
Query?: Record<string, GraphQLResolver>;
|
|
42
|
+
Mutation?: Record<string, GraphQLResolver>;
|
|
43
|
+
Subscription?: Record<string, GraphQLSubscriptionResolver>;
|
|
44
|
+
[key: string]: any;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* GraphQL execution options
|
|
48
|
+
*/
|
|
49
|
+
export interface GraphQLExecutionOptions {
|
|
50
|
+
schema: GraphQLSchema;
|
|
51
|
+
query: string;
|
|
52
|
+
variables?: Record<string, any>;
|
|
53
|
+
operationName?: string;
|
|
54
|
+
context?: GraphQLContext;
|
|
55
|
+
rootValue?: any;
|
|
56
|
+
fieldResolver?: GraphQLFieldResolver<any, any>;
|
|
57
|
+
typeResolver?: GraphQLTypeResolver<any, any>;
|
|
58
|
+
subscriptionFieldResolver?: GraphQLFieldResolver<any, any>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* GraphQL configuration options
|
|
62
|
+
*/
|
|
63
|
+
export interface GraphQLOptions {
|
|
64
|
+
adapter?: any;
|
|
65
|
+
schema?: any;
|
|
66
|
+
typeDefs?: string | string[];
|
|
67
|
+
resolvers?: GraphQLResolvers;
|
|
68
|
+
pothosSchema?: any;
|
|
69
|
+
context?: (req: HttpRequest, res: HttpResponse) => GraphQLContext | Promise<GraphQLContext>;
|
|
70
|
+
path?: string;
|
|
71
|
+
playgroundPath?: string;
|
|
72
|
+
enablePlayground?: boolean;
|
|
73
|
+
enableJIT?: boolean;
|
|
74
|
+
jitCacheTTL?: number;
|
|
75
|
+
enableIntrospection?: boolean;
|
|
76
|
+
enableSubscriptions?: boolean;
|
|
77
|
+
enableBatching?: boolean;
|
|
78
|
+
formatError?: (error: GraphQLError) => any;
|
|
79
|
+
debug?: boolean;
|
|
80
|
+
validationRules?: any[];
|
|
81
|
+
maxDepth?: number;
|
|
82
|
+
maxComplexity?: number;
|
|
83
|
+
rateLimit?: {
|
|
84
|
+
queries?: {
|
|
85
|
+
requests: number;
|
|
86
|
+
window: number;
|
|
87
|
+
};
|
|
88
|
+
mutations?: {
|
|
89
|
+
requests: number;
|
|
90
|
+
window: number;
|
|
91
|
+
};
|
|
92
|
+
subscriptions?: {
|
|
93
|
+
requests: number;
|
|
94
|
+
window: number;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
enableCache?: boolean;
|
|
98
|
+
cacheAdapter?: any;
|
|
99
|
+
cacheTTL?: number;
|
|
100
|
+
requireAuth?: boolean;
|
|
101
|
+
authScopes?: string[];
|
|
102
|
+
extensions?: any[];
|
|
103
|
+
plugins?: GraphQLPlugin[];
|
|
104
|
+
rootValue?: any;
|
|
105
|
+
fieldResolver?: GraphQLFieldResolver<any, any>;
|
|
106
|
+
typeResolver?: GraphQLTypeResolver<any, any>;
|
|
107
|
+
parseOptions?: any;
|
|
108
|
+
validationTypeInfo?: any;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* GraphQL plugin interface
|
|
112
|
+
*/
|
|
113
|
+
export interface GraphQLPlugin {
|
|
114
|
+
name: string;
|
|
115
|
+
requestDidStart?: (context: GraphQLRequestContext) => GraphQLRequestListener | void;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* GraphQL request context
|
|
119
|
+
*/
|
|
120
|
+
export interface GraphQLRequestContext {
|
|
121
|
+
request: GraphQLRequest;
|
|
122
|
+
response?: GraphQLResponse;
|
|
123
|
+
context: GraphQLContext;
|
|
124
|
+
schema: GraphQLSchema;
|
|
125
|
+
operation?: any;
|
|
126
|
+
operationName?: string | null;
|
|
127
|
+
document?: any;
|
|
128
|
+
metrics?: GraphQLMetrics;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* GraphQL request listener (for plugins)
|
|
132
|
+
*/
|
|
133
|
+
export interface GraphQLRequestListener {
|
|
134
|
+
parsingDidStart?: () => void;
|
|
135
|
+
validationDidStart?: () => void;
|
|
136
|
+
executionDidStart?: () => void;
|
|
137
|
+
didEncounterErrors?: (errors: readonly GraphQLError[]) => void;
|
|
138
|
+
willSendResponse?: (context: GraphQLRequestContext) => void;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* GraphQL request
|
|
142
|
+
*/
|
|
143
|
+
export interface GraphQLRequest {
|
|
144
|
+
query: string;
|
|
145
|
+
variables?: Record<string, any>;
|
|
146
|
+
operationName?: string | null;
|
|
147
|
+
extensions?: Record<string, any>;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* GraphQL response
|
|
151
|
+
*/
|
|
152
|
+
export interface GraphQLResponse {
|
|
153
|
+
data?: any;
|
|
154
|
+
errors?: readonly GraphQLError[];
|
|
155
|
+
extensions?: Record<string, any>;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* GraphQL execution metrics
|
|
159
|
+
*/
|
|
160
|
+
export interface GraphQLMetrics {
|
|
161
|
+
startTime: number;
|
|
162
|
+
endTime?: number;
|
|
163
|
+
duration?: number;
|
|
164
|
+
parsing?: number;
|
|
165
|
+
validation?: number;
|
|
166
|
+
execution?: number;
|
|
167
|
+
fieldResolution?: Record<string, number>;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* GraphQL subscription options
|
|
171
|
+
*/
|
|
172
|
+
export interface GraphQLSubscriptionOptions {
|
|
173
|
+
onConnect?: (connectionParams: any, websocket: any, context: any) => any | Promise<any>;
|
|
174
|
+
onDisconnect?: (websocket: any, context: any) => void | Promise<void>;
|
|
175
|
+
keepAlive?: number;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* GraphQL DataLoader options
|
|
179
|
+
*/
|
|
180
|
+
export interface DataLoaderOptions<K, V> {
|
|
181
|
+
batch?: boolean;
|
|
182
|
+
maxBatchSize?: number;
|
|
183
|
+
cache?: boolean;
|
|
184
|
+
cacheKeyFn?: (key: K) => any;
|
|
185
|
+
cacheMap?: Map<any, Promise<V>>;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* GraphQL field complexity calculator
|
|
189
|
+
*/
|
|
190
|
+
export type ComplexityEstimator = (options: {
|
|
191
|
+
type: any;
|
|
192
|
+
field: any;
|
|
193
|
+
args: Record<string, any>;
|
|
194
|
+
childComplexity: number;
|
|
195
|
+
}) => number;
|
|
196
|
+
/**
|
|
197
|
+
* GraphQL query complexity options
|
|
198
|
+
*/
|
|
199
|
+
export interface QueryComplexityOptions {
|
|
200
|
+
maximumComplexity: number;
|
|
201
|
+
variables?: Record<string, any>;
|
|
202
|
+
onComplete?: (complexity: number) => void;
|
|
203
|
+
estimators?: ComplexityEstimator[];
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* GraphQL depth limit options
|
|
207
|
+
*/
|
|
208
|
+
export interface DepthLimitOptions {
|
|
209
|
+
maxDepth: number;
|
|
210
|
+
callback?: (obj: any) => void;
|
|
211
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/graphql/types.ts"],"names":[],"mappings":""}
|
|
@@ -47,6 +47,7 @@ export class MoroHttpServer {
|
|
|
47
47
|
MoroHttpServer.BUFFER_POOLS.set(size, []);
|
|
48
48
|
for (let i = 0; i < 50; i++) {
|
|
49
49
|
// 50 buffers per size
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
50
51
|
MoroHttpServer.BUFFER_POOLS.get(size).push(Buffer.allocUnsafe(size));
|
|
51
52
|
}
|
|
52
53
|
}
|
|
@@ -55,7 +56,9 @@ export class MoroHttpServer {
|
|
|
55
56
|
// Find the smallest buffer that fits
|
|
56
57
|
for (const poolSize of MoroHttpServer.BUFFER_SIZES) {
|
|
57
58
|
if (size <= poolSize) {
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
58
60
|
const pool = MoroHttpServer.BUFFER_POOLS.get(poolSize);
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
59
62
|
return pool.length > 0 ? pool.pop() : Buffer.allocUnsafe(poolSize);
|
|
60
63
|
}
|
|
61
64
|
}
|
|
@@ -65,6 +68,7 @@ export class MoroHttpServer {
|
|
|
65
68
|
// Return buffer to appropriate pool
|
|
66
69
|
const size = buffer.length;
|
|
67
70
|
if (MoroHttpServer.BUFFER_POOLS.has(size)) {
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
68
72
|
const pool = MoroHttpServer.BUFFER_POOLS.get(size);
|
|
69
73
|
if (pool.length < 50) {
|
|
70
74
|
// Don't let pools grow too large
|
|
@@ -147,6 +151,7 @@ export class MoroHttpServer {
|
|
|
147
151
|
if (!this.routesBySegmentCount.has(segmentCount)) {
|
|
148
152
|
this.routesBySegmentCount.set(segmentCount, []);
|
|
149
153
|
}
|
|
154
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
150
155
|
this.routesBySegmentCount.get(segmentCount).push(route);
|
|
151
156
|
}
|
|
152
157
|
}
|
|
@@ -165,6 +170,7 @@ export class MoroHttpServer {
|
|
|
165
170
|
const originalParams = httpReq.params;
|
|
166
171
|
try {
|
|
167
172
|
// Optimized URL and query parsing with object pooling
|
|
173
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
168
174
|
const urlString = req.url;
|
|
169
175
|
const queryIndex = urlString.indexOf('?');
|
|
170
176
|
if (queryIndex === -1) {
|
|
@@ -200,6 +206,7 @@ export class MoroHttpServer {
|
|
|
200
206
|
return;
|
|
201
207
|
}
|
|
202
208
|
// Find matching route
|
|
209
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
203
210
|
const route = this.findRoute(req.method, httpReq.path);
|
|
204
211
|
if (!route) {
|
|
205
212
|
// 404 response with pre-compiled buffer
|
|
@@ -287,6 +294,7 @@ export class MoroHttpServer {
|
|
|
287
294
|
// Optimized: Check if object is empty without Object.keys()
|
|
288
295
|
if (originalParams) {
|
|
289
296
|
let isEmpty = true;
|
|
297
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
290
298
|
for (const _key in originalParams) {
|
|
291
299
|
isEmpty = false;
|
|
292
300
|
break;
|
|
@@ -297,6 +305,7 @@ export class MoroHttpServer {
|
|
|
297
305
|
}
|
|
298
306
|
if (httpReq.params && httpReq.params !== originalParams) {
|
|
299
307
|
let isEmpty = true;
|
|
308
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
300
309
|
for (const _key in httpReq.params) {
|
|
301
310
|
isEmpty = false;
|
|
302
311
|
break;
|
|
@@ -311,6 +320,7 @@ export class MoroHttpServer {
|
|
|
311
320
|
// Optimized: Check if object is empty without Object.keys()
|
|
312
321
|
if (originalParams) {
|
|
313
322
|
let isEmpty = true;
|
|
323
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
314
324
|
for (const _key in originalParams) {
|
|
315
325
|
isEmpty = false;
|
|
316
326
|
break;
|
|
@@ -321,6 +331,7 @@ export class MoroHttpServer {
|
|
|
321
331
|
}
|
|
322
332
|
if (httpReq.params && httpReq.params !== originalParams) {
|
|
323
333
|
let isEmpty = true;
|
|
334
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
324
335
|
for (const _key in httpReq.params) {
|
|
325
336
|
isEmpty = false;
|
|
326
337
|
break;
|
|
@@ -368,6 +379,7 @@ export class MoroHttpServer {
|
|
|
368
379
|
normalizePath(path) {
|
|
369
380
|
// Check cache first
|
|
370
381
|
if (this.pathNormalizationCache.has(path)) {
|
|
382
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
371
383
|
return this.pathNormalizationCache.get(path);
|
|
372
384
|
}
|
|
373
385
|
// Normalization: remove trailing slash (except root), decode once
|
|
@@ -665,7 +677,7 @@ export class MoroHttpServer {
|
|
|
665
677
|
httpRes.setHeader('Cache-Control', 'public, max-age=31536000'); // 1 year for static files
|
|
666
678
|
httpRes.end(data);
|
|
667
679
|
}
|
|
668
|
-
catch
|
|
680
|
+
catch {
|
|
669
681
|
httpRes.status(404).json({ success: false, error: 'File not found' });
|
|
670
682
|
}
|
|
671
683
|
};
|
|
@@ -875,6 +887,7 @@ export class MoroHttpServer {
|
|
|
875
887
|
const cacheKey = `${method}:${path}`;
|
|
876
888
|
// Check cache first (hot path optimization) - BEFORE any other work
|
|
877
889
|
if (this.routeCache.has(cacheKey)) {
|
|
890
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
878
891
|
return this.routeCache.get(cacheKey);
|
|
879
892
|
}
|
|
880
893
|
// Normalize path for consistent matching (only if not cached)
|
|
@@ -882,6 +895,7 @@ export class MoroHttpServer {
|
|
|
882
895
|
const normalizedCacheKey = normalizedPath !== path ? `${method}:${normalizedPath}` : cacheKey;
|
|
883
896
|
// Check cache again with normalized path
|
|
884
897
|
if (normalizedPath !== path && this.routeCache.has(normalizedCacheKey)) {
|
|
898
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
885
899
|
return this.routeCache.get(normalizedCacheKey);
|
|
886
900
|
}
|
|
887
901
|
// Phase 1: O(1) static route lookup
|
|
@@ -1084,6 +1098,7 @@ export const middleware = {
|
|
|
1084
1098
|
return (req, res, next) => {
|
|
1085
1099
|
const start = Date.now();
|
|
1086
1100
|
res.on('finish', () => {
|
|
1101
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1087
1102
|
const duration = Date.now() - start;
|
|
1088
1103
|
// Request completed - logged by framework
|
|
1089
1104
|
});
|
|
@@ -1139,7 +1154,7 @@ export const middleware = {
|
|
|
1139
1154
|
try {
|
|
1140
1155
|
stats = await fs.stat(filePath);
|
|
1141
1156
|
}
|
|
1142
|
-
catch
|
|
1157
|
+
catch {
|
|
1143
1158
|
next(); // File not found, let other middleware handle
|
|
1144
1159
|
return;
|
|
1145
1160
|
}
|
|
@@ -1158,7 +1173,7 @@ export const middleware = {
|
|
|
1158
1173
|
break;
|
|
1159
1174
|
}
|
|
1160
1175
|
}
|
|
1161
|
-
catch
|
|
1176
|
+
catch {
|
|
1162
1177
|
// Continue to next index file
|
|
1163
1178
|
}
|
|
1164
1179
|
}
|
|
@@ -1225,7 +1240,7 @@ export const middleware = {
|
|
|
1225
1240
|
const data = await fs.readFile(filePath);
|
|
1226
1241
|
res.end(data);
|
|
1227
1242
|
}
|
|
1228
|
-
catch
|
|
1243
|
+
catch {
|
|
1229
1244
|
res.status(500).json({ success: false, error: 'Internal server error' });
|
|
1230
1245
|
}
|
|
1231
1246
|
};
|
|
@@ -1253,6 +1268,7 @@ export const middleware = {
|
|
|
1253
1268
|
return;
|
|
1254
1269
|
}
|
|
1255
1270
|
// Validate each file
|
|
1271
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1256
1272
|
for (const [fieldName, file] of Object.entries(files)) {
|
|
1257
1273
|
const fileData = file;
|
|
1258
1274
|
// Validate file size
|
|
@@ -1290,6 +1306,7 @@ export const middleware = {
|
|
|
1290
1306
|
let templateContent;
|
|
1291
1307
|
// Check cache first
|
|
1292
1308
|
if (options.cache && templateCache.has(templatePath)) {
|
|
1309
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1293
1310
|
templateContent = templateCache.get(templatePath);
|
|
1294
1311
|
}
|
|
1295
1312
|
else {
|
|
@@ -1336,6 +1353,7 @@ export const middleware = {
|
|
|
1336
1353
|
try {
|
|
1337
1354
|
let layoutContent;
|
|
1338
1355
|
if (options.cache && templateCache.has(layoutPath)) {
|
|
1356
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1339
1357
|
layoutContent = templateCache.get(layoutPath);
|
|
1340
1358
|
}
|
|
1341
1359
|
else {
|
|
@@ -1346,14 +1364,14 @@ export const middleware = {
|
|
|
1346
1364
|
}
|
|
1347
1365
|
rendered = layoutContent.replace(/\{\{body\}\}/, rendered);
|
|
1348
1366
|
}
|
|
1349
|
-
catch
|
|
1367
|
+
catch {
|
|
1350
1368
|
// Layout not found, use template as-is
|
|
1351
1369
|
}
|
|
1352
1370
|
}
|
|
1353
1371
|
res.setHeader('Content-Type', 'text/html');
|
|
1354
1372
|
res.end(rendered);
|
|
1355
1373
|
}
|
|
1356
|
-
catch
|
|
1374
|
+
catch {
|
|
1357
1375
|
res.status(500).json({ success: false, error: 'Template rendering failed' });
|
|
1358
1376
|
}
|
|
1359
1377
|
};
|
|
@@ -1378,7 +1396,7 @@ export const middleware = {
|
|
|
1378
1396
|
return pushStream;
|
|
1379
1397
|
}
|
|
1380
1398
|
}
|
|
1381
|
-
catch
|
|
1399
|
+
catch {
|
|
1382
1400
|
// Push failed, continue normally
|
|
1383
1401
|
}
|
|
1384
1402
|
}
|
|
@@ -1456,7 +1474,8 @@ export const middleware = {
|
|
|
1456
1474
|
res.sendRange = async (filePath, stats) => {
|
|
1457
1475
|
try {
|
|
1458
1476
|
const fs = await import('fs/promises');
|
|
1459
|
-
|
|
1477
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1478
|
+
const _path = await import('path');
|
|
1460
1479
|
if (!stats) {
|
|
1461
1480
|
stats = await fs.stat(filePath);
|
|
1462
1481
|
}
|
|
@@ -1515,6 +1534,7 @@ export const middleware = {
|
|
|
1515
1534
|
for (const { start, end } of ranges) {
|
|
1516
1535
|
if (start >= fileSize || end >= fileSize)
|
|
1517
1536
|
continue;
|
|
1537
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1518
1538
|
const chunkSize = end - start + 1;
|
|
1519
1539
|
res.write(`\r\n--${boundary}\r\n`);
|
|
1520
1540
|
res.write(`Content-Range: bytes ${start}-${end}/${fileSize}\r\n\r\n`);
|
|
@@ -1531,7 +1551,7 @@ export const middleware = {
|
|
|
1531
1551
|
res.end();
|
|
1532
1552
|
}
|
|
1533
1553
|
}
|
|
1534
|
-
catch
|
|
1554
|
+
catch {
|
|
1535
1555
|
res.status(500).json({ success: false, error: 'Range request failed' });
|
|
1536
1556
|
}
|
|
1537
1557
|
};
|
|
@@ -1540,6 +1560,7 @@ export const middleware = {
|
|
|
1540
1560
|
},
|
|
1541
1561
|
// CSRF Protection middleware
|
|
1542
1562
|
csrf: (options = {}) => {
|
|
1563
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1543
1564
|
const secret = options.secret || 'moro-csrf-secret';
|
|
1544
1565
|
const tokenLength = options.tokenLength || 32;
|
|
1545
1566
|
const cookieName = options.cookieName || '_csrf';
|
|
@@ -1566,6 +1587,7 @@ export const middleware = {
|
|
|
1566
1587
|
return req._csrfToken;
|
|
1567
1588
|
};
|
|
1568
1589
|
// Skip verification for safe methods
|
|
1590
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1569
1591
|
if (ignoreMethods.includes(req.method)) {
|
|
1570
1592
|
next();
|
|
1571
1593
|
return;
|