silgi 0.33.1 → 0.34.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.
@@ -1,15 +1,15 @@
1
1
  import { createConsola } from 'consola';
2
2
  import { defu } from 'defu';
3
3
  import { createHooks } from 'hookable';
4
- import { c as createRouteRules } from '../_chunks/routeRules.mjs';
4
+ import { createRouter, addRoute, findRoute } from 'rou3';
5
5
  import { getContext } from 'unctx';
6
6
  import { Buffer } from 'node:buffer';
7
7
  import { klona } from 'klona';
8
8
  import { useSilgiRuntimeConfig } from 'silgi/runtime';
9
9
  import { createStorage as createStorage$1, builtinDrivers, prefixStorage } from 'unstorage';
10
+ import { FastURL, FastResponse } from 'srvx';
10
11
  import { isRuntimePresents } from 'silgi/kit';
11
12
  export { s as silgiCLICtx, t as tryUseSilgiCLI, u as useSilgiCLI } from '../_chunks/silgiApp.mjs';
12
- import 'ufo';
13
13
 
14
14
  const silgiCtx = getContext("silgi");
15
15
  function useSilgi() {
@@ -35,387 +35,133 @@ function tryUseSilgi() {
35
35
  return silgiCtx.tryUse();
36
36
  }
37
37
 
38
- var HttpStatus = /* @__PURE__ */ ((HttpStatus2) => {
39
- HttpStatus2[HttpStatus2["CONTINUE"] = 100] = "CONTINUE";
40
- HttpStatus2[HttpStatus2["SWITCHING_PROTOCOLS"] = 101] = "SWITCHING_PROTOCOLS";
41
- HttpStatus2[HttpStatus2["PROCESSING"] = 102] = "PROCESSING";
42
- HttpStatus2[HttpStatus2["EARLY_HINTS"] = 103] = "EARLY_HINTS";
43
- HttpStatus2[HttpStatus2["OK"] = 200] = "OK";
44
- HttpStatus2[HttpStatus2["CREATED"] = 201] = "CREATED";
45
- HttpStatus2[HttpStatus2["ACCEPTED"] = 202] = "ACCEPTED";
46
- HttpStatus2[HttpStatus2["NON_AUTHORITATIVE_INFORMATION"] = 203] = "NON_AUTHORITATIVE_INFORMATION";
47
- HttpStatus2[HttpStatus2["NO_CONTENT"] = 204] = "NO_CONTENT";
48
- HttpStatus2[HttpStatus2["RESET_CONTENT"] = 205] = "RESET_CONTENT";
49
- HttpStatus2[HttpStatus2["PARTIAL_CONTENT"] = 206] = "PARTIAL_CONTENT";
50
- HttpStatus2[HttpStatus2["MULTI_STATUS"] = 207] = "MULTI_STATUS";
51
- HttpStatus2[HttpStatus2["ALREADY_REPORTED"] = 208] = "ALREADY_REPORTED";
52
- HttpStatus2[HttpStatus2["IM_USED"] = 226] = "IM_USED";
53
- HttpStatus2[HttpStatus2["MULTIPLE_CHOICES"] = 300] = "MULTIPLE_CHOICES";
54
- HttpStatus2[HttpStatus2["MOVED_PERMANENTLY"] = 301] = "MOVED_PERMANENTLY";
55
- HttpStatus2[HttpStatus2["FOUND"] = 302] = "FOUND";
56
- HttpStatus2[HttpStatus2["SEE_OTHER"] = 303] = "SEE_OTHER";
57
- HttpStatus2[HttpStatus2["NOT_MODIFIED"] = 304] = "NOT_MODIFIED";
58
- HttpStatus2[HttpStatus2["USE_PROXY"] = 305] = "USE_PROXY";
59
- HttpStatus2[HttpStatus2["TEMPORARY_REDIRECT"] = 307] = "TEMPORARY_REDIRECT";
60
- HttpStatus2[HttpStatus2["PERMANENT_REDIRECT"] = 308] = "PERMANENT_REDIRECT";
61
- HttpStatus2[HttpStatus2["BAD_REQUEST"] = 400] = "BAD_REQUEST";
62
- HttpStatus2[HttpStatus2["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
63
- HttpStatus2[HttpStatus2["PAYMENT_REQUIRED"] = 402] = "PAYMENT_REQUIRED";
64
- HttpStatus2[HttpStatus2["FORBIDDEN"] = 403] = "FORBIDDEN";
65
- HttpStatus2[HttpStatus2["NOT_FOUND"] = 404] = "NOT_FOUND";
66
- HttpStatus2[HttpStatus2["METHOD_NOT_ALLOWED"] = 405] = "METHOD_NOT_ALLOWED";
67
- HttpStatus2[HttpStatus2["NOT_ACCEPTABLE"] = 406] = "NOT_ACCEPTABLE";
68
- HttpStatus2[HttpStatus2["PROXY_AUTHENTICATION_REQUIRED"] = 407] = "PROXY_AUTHENTICATION_REQUIRED";
69
- HttpStatus2[HttpStatus2["REQUEST_TIMEOUT"] = 408] = "REQUEST_TIMEOUT";
70
- HttpStatus2[HttpStatus2["CONFLICT"] = 409] = "CONFLICT";
71
- HttpStatus2[HttpStatus2["GONE"] = 410] = "GONE";
72
- HttpStatus2[HttpStatus2["LENGTH_REQUIRED"] = 411] = "LENGTH_REQUIRED";
73
- HttpStatus2[HttpStatus2["PRECONDITION_FAILED"] = 412] = "PRECONDITION_FAILED";
74
- HttpStatus2[HttpStatus2["PAYLOAD_TOO_LARGE"] = 413] = "PAYLOAD_TOO_LARGE";
75
- HttpStatus2[HttpStatus2["URI_TOO_LONG"] = 414] = "URI_TOO_LONG";
76
- HttpStatus2[HttpStatus2["UNSUPPORTED_MEDIA_TYPE"] = 415] = "UNSUPPORTED_MEDIA_TYPE";
77
- HttpStatus2[HttpStatus2["RANGE_NOT_SATISFIABLE"] = 416] = "RANGE_NOT_SATISFIABLE";
78
- HttpStatus2[HttpStatus2["EXPECTATION_FAILED"] = 417] = "EXPECTATION_FAILED";
79
- HttpStatus2[HttpStatus2["IM_A_TEAPOT"] = 418] = "IM_A_TEAPOT";
80
- HttpStatus2[HttpStatus2["MISDIRECTED_REQUEST"] = 421] = "MISDIRECTED_REQUEST";
81
- HttpStatus2[HttpStatus2["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
82
- HttpStatus2[HttpStatus2["LOCKED"] = 423] = "LOCKED";
83
- HttpStatus2[HttpStatus2["FAILED_DEPENDENCY"] = 424] = "FAILED_DEPENDENCY";
84
- HttpStatus2[HttpStatus2["TOO_EARLY"] = 425] = "TOO_EARLY";
85
- HttpStatus2[HttpStatus2["UPGRADE_REQUIRED"] = 426] = "UPGRADE_REQUIRED";
86
- HttpStatus2[HttpStatus2["PRECONDITION_REQUIRED"] = 428] = "PRECONDITION_REQUIRED";
87
- HttpStatus2[HttpStatus2["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS";
88
- HttpStatus2[HttpStatus2["REQUEST_HEADER_FIELDS_TOO_LARGE"] = 431] = "REQUEST_HEADER_FIELDS_TOO_LARGE";
89
- HttpStatus2[HttpStatus2["UNAVAILABLE_FOR_LEGAL_REASONS"] = 451] = "UNAVAILABLE_FOR_LEGAL_REASONS";
90
- HttpStatus2[HttpStatus2["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
91
- HttpStatus2[HttpStatus2["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED";
92
- HttpStatus2[HttpStatus2["BAD_GATEWAY"] = 502] = "BAD_GATEWAY";
93
- HttpStatus2[HttpStatus2["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE";
94
- HttpStatus2[HttpStatus2["GATEWAY_TIMEOUT"] = 504] = "GATEWAY_TIMEOUT";
95
- HttpStatus2[HttpStatus2["HTTP_VERSION_NOT_SUPPORTED"] = 505] = "HTTP_VERSION_NOT_SUPPORTED";
96
- HttpStatus2[HttpStatus2["VARIANT_ALSO_NEGOTIATES"] = 506] = "VARIANT_ALSO_NEGOTIATES";
97
- HttpStatus2[HttpStatus2["INSUFFICIENT_STORAGE"] = 507] = "INSUFFICIENT_STORAGE";
98
- HttpStatus2[HttpStatus2["LOOP_DETECTED"] = 508] = "LOOP_DETECTED";
99
- HttpStatus2[HttpStatus2["NOT_EXTENDED"] = 510] = "NOT_EXTENDED";
100
- HttpStatus2[HttpStatus2["NETWORK_AUTHENTICATION_REQUIRED"] = 511] = "NETWORK_AUTHENTICATION_REQUIRED";
101
- return HttpStatus2;
102
- })(HttpStatus || {});
103
- var ErrorSeverity = /* @__PURE__ */ ((ErrorSeverity2) => {
104
- ErrorSeverity2["DEBUG"] = "DEBUG";
105
- ErrorSeverity2["INFO"] = "INFO";
106
- ErrorSeverity2["WARNING"] = "WARNING";
107
- ErrorSeverity2["ERROR"] = "ERROR";
108
- ErrorSeverity2["CRITICAL"] = "CRITICAL";
109
- return ErrorSeverity2;
110
- })(ErrorSeverity || {});
111
- var ErrorCategory = /* @__PURE__ */ ((ErrorCategory2) => {
112
- ErrorCategory2["AUTHENTICATION"] = "auth";
113
- ErrorCategory2["AUTHORIZATION"] = "authorization";
114
- ErrorCategory2["VALIDATION"] = "validation";
115
- ErrorCategory2["BUSINESS"] = "business";
116
- ErrorCategory2["INFRASTRUCTURE"] = "infrastructure";
117
- ErrorCategory2["EXTERNAL"] = "external";
118
- ErrorCategory2["UNKNOWN"] = "unknown";
119
- return ErrorCategory2;
120
- })(ErrorCategory || {});
121
- class ErrorFactory {
122
- static createMetadata(metadata) {
123
- return {
124
- timestamp: Date.now(),
125
- ...metadata
126
- };
38
+ const EmptyObject = /* @__PURE__ */ (() => {
39
+ const C = function() {
40
+ };
41
+ C.prototype = /* @__PURE__ */ Object.create(null);
42
+ return C;
43
+ })();
44
+
45
+ function hasProp(obj, prop) {
46
+ try {
47
+ return prop in obj;
48
+ } catch {
49
+ return false;
127
50
  }
128
- static create(options) {
129
- return new SilgiError({
130
- code: options.code ?? options.httpStatus ?? 500 /* INTERNAL_SERVER_ERROR */,
131
- message: options.message,
132
- category: options.category ?? "unknown" /* UNKNOWN */,
133
- severity: options.severity ?? "ERROR" /* ERROR */,
134
- httpStatus: options.httpStatus ?? 500 /* INTERNAL_SERVER_ERROR */,
135
- metadata: this.createMetadata(options.metadata),
136
- cause: options.cause,
137
- context: options.context
138
- });
51
+ }
52
+ function isJSONSerializable(value, _type) {
53
+ if (value === null || value === void 0) {
54
+ return true;
139
55
  }
140
- // Predefined error creators
141
- static authenticationError(message, context) {
142
- return this.create({
143
- message,
144
- code: 401,
145
- category: "auth" /* AUTHENTICATION */,
146
- severity: "ERROR" /* ERROR */,
147
- httpStatus: 401 /* UNAUTHORIZED */,
148
- context
149
- });
56
+ if (_type !== "object") {
57
+ return _type === "boolean" || _type === "number" || _type === "string";
150
58
  }
151
- static authorizationError(message, context) {
152
- return this.create({
153
- message,
154
- code: 403,
155
- category: "authorization" /* AUTHORIZATION */,
156
- severity: "ERROR" /* ERROR */,
157
- httpStatus: 403 /* FORBIDDEN */,
158
- context
159
- });
59
+ if (typeof value.toJSON === "function") {
60
+ return true;
160
61
  }
161
- static validationError(message, context) {
162
- return this.create({
163
- message,
164
- code: 400,
165
- category: "validation" /* VALIDATION */,
166
- severity: "WARNING" /* WARNING */,
167
- httpStatus: 400 /* BAD_REQUEST */,
168
- context
169
- });
62
+ if (Array.isArray(value)) {
63
+ return true;
170
64
  }
171
- static notFoundError(message, context) {
172
- return this.create({
173
- message,
174
- code: 404,
175
- category: "business" /* BUSINESS */,
176
- severity: "WARNING" /* WARNING */,
177
- httpStatus: 404 /* NOT_FOUND */,
178
- context
179
- });
65
+ if (typeof value.pipe === "function" || typeof value.pipeTo === "function") {
66
+ return false;
180
67
  }
181
- static internalError(message, cause) {
182
- return this.create({
183
- message,
184
- code: 500,
185
- category: "infrastructure" /* INFRASTRUCTURE */,
186
- severity: "CRITICAL" /* CRITICAL */,
187
- httpStatus: 500 /* INTERNAL_SERVER_ERROR */,
188
- cause
189
- });
68
+ if (value instanceof EmptyObject) {
69
+ return true;
190
70
  }
71
+ const proto = Object.getPrototypeOf(value);
72
+ return proto === Object.prototype || proto === null;
191
73
  }
74
+
75
+ const DISALLOWED_STATUS_CHARS = /[^\u0009\u0020-\u007E]/g;
76
+ function sanitizeStatusMessage(statusMessage = "") {
77
+ return statusMessage.replace(DISALLOWED_STATUS_CHARS, "");
78
+ }
79
+ function sanitizeStatusCode(statusCode, defaultStatusCode = 200) {
80
+ if (!statusCode) {
81
+ return defaultStatusCode;
82
+ }
83
+ if (typeof statusCode === "string") {
84
+ statusCode = Number.parseInt(statusCode, 10);
85
+ }
86
+ if (statusCode < 100 || statusCode > 999) {
87
+ return defaultStatusCode;
88
+ }
89
+ return statusCode;
90
+ }
91
+
192
92
  class SilgiError extends Error {
193
- code;
194
- category;
195
- severity;
196
- httpStatus;
197
- metadata;
198
- context;
93
+ static __silgi_error__ = true;
94
+ statusCode = 500;
95
+ fatal = false;
96
+ unhandled = false;
97
+ statusMessage;
98
+ data;
199
99
  cause;
200
- constructor(error) {
201
- super(error.message);
202
- this.name = "SilgiError";
203
- this.code = error.code;
204
- this.category = error.category;
205
- this.severity = error.severity;
206
- this.httpStatus = error.httpStatus;
207
- this.metadata = error.metadata ?? { timestamp: Date.now() };
208
- this.context = error.context;
209
- this.cause = error.cause;
210
- if (Error.captureStackTrace) {
211
- Error.captureStackTrace(this, this.constructor);
212
- }
213
- }
214
- toString() {
215
- let str = `${this.name} [${this.code}] ${this.severity}: ${this.message}`;
216
- str += `
217
- Category: ${this.category}`;
218
- str += `
219
- HTTP Status: ${this.httpStatus}`;
220
- if (this.context) {
221
- str += `
222
- Context: ${JSON.stringify(this.context, null, 2)}`;
223
- }
224
- if (this.metadata) {
225
- str += `
226
- Metadata: ${JSON.stringify(this.metadata, null, 2)}`;
227
- }
228
- if (this.stack) {
229
- str += `
230
- ${this.stack}`;
100
+ constructor(message, opts = {}) {
101
+ super(message, opts);
102
+ if (opts.cause && !this.cause) {
103
+ this.cause = opts.cause;
231
104
  }
232
- return str;
233
105
  }
234
106
  toJSON() {
235
- return {
236
- name: this.name,
237
- code: this.code,
107
+ const obj = {
238
108
  message: this.message,
239
- category: this.category,
240
- severity: this.severity,
241
- httpStatus: this.httpStatus,
242
- metadata: this.metadata,
243
- context: this.context,
244
- stack: this.stack
109
+ statusCode: sanitizeStatusCode(this.statusCode, 500)
245
110
  };
246
- }
247
- static isError(error) {
248
- return error instanceof SilgiError || typeof error === "object" && error !== null && "name" in error && error.name === "SilgiError";
249
- }
250
- static from(error) {
251
- if (error instanceof SilgiError) {
252
- return error;
111
+ if (this.statusMessage) {
112
+ obj.statusMessage = sanitizeStatusMessage(this.statusMessage);
253
113
  }
254
- return ErrorFactory.internalError(
255
- error instanceof Error ? error.message : String(error),
256
- error instanceof Error ? error : void 0
257
- );
114
+ if (this.data !== void 0) {
115
+ obj.data = this.data;
116
+ }
117
+ return obj;
258
118
  }
259
119
  }
260
- function isBaseError(error) {
261
- return typeof error === "object" && error !== null && "code" in error && "message" in error && "category" in error && "severity" in error && "httpStatus" in error;
262
- }
263
-
264
- function parseURI(uri, uris) {
265
- if (!uri) {
266
- throw ErrorFactory.create({
267
- message: "URI cannot be empty",
268
- httpStatus: HttpStatus.BAD_REQUEST,
269
- context: { uri }
270
- });
271
- }
272
- if (!uris) {
273
- throw ErrorFactory.create({
274
- message: "URIs configuration is not provided",
275
- httpStatus: HttpStatus.INTERNAL_SERVER_ERROR,
276
- context: { uri }
277
- });
120
+ function createError(input) {
121
+ if (typeof input === "string") {
122
+ return new SilgiError(input);
278
123
  }
279
- const cleanUri = uri.replace(/^\/*(srn\/)?/, "").replace(/\/*$/, "");
280
- const [path, queryString] = cleanUri.split("?");
281
- const parts = path.split("/");
282
- const query = queryString ? Object.fromEntries(
283
- queryString.split("&").map((param) => param.split("="))
284
- ) : void 0;
285
- const method = query?.method ? query?.method.toLowerCase() : void 0;
286
- const namespaceName = parts[0];
287
- const serviceName = parts[1];
288
- const methodName = method || parts[2];
289
- const actionName = method ? parts[2] : parts[3];
290
- if (!namespaceName || !serviceName || !methodName || !actionName) {
291
- throw ErrorFactory.create({
292
- message: "Invalid URI format: Insufficient path segments",
293
- httpStatus: HttpStatus.BAD_REQUEST,
294
- context: {
295
- uri,
296
- cleanUri,
297
- partsLength: parts.length,
298
- method,
299
- namespaceName,
300
- serviceName,
301
- methodName,
302
- actionName
303
- }
304
- });
305
- }
306
- const baseUri = `${namespaceName}/${serviceName}/${methodName}/${actionName}`;
307
- const paramStartIndex = method ? 3 : 4;
308
- const parameters = parts.slice(paramStartIndex);
309
- const normalizedUri = method ? `${namespaceName}/${serviceName}/${method}/${actionName}${parameters.length ? `/${parameters.join("/")}` : ""}` : cleanUri;
310
- const template = uris[baseUri];
311
- if (template === void 0) {
312
- throw ErrorFactory.create({
313
- message: "No route found for URI",
314
- httpStatus: HttpStatus.NOT_FOUND,
315
- context: {
316
- uri,
317
- baseUri
318
- }
319
- });
320
- }
321
- if (template === "") {
322
- if (parameters.length > 0) {
323
- throw ErrorFactory.create({
324
- message: "No parameters expected for this route",
325
- httpStatus: HttpStatus.BAD_REQUEST,
326
- context: {
327
- uri,
328
- baseUri,
329
- extraParams: parameters
124
+ const cause = input.cause;
125
+ const err = new SilgiError(input.message ?? input.statusMessage ?? "", {
126
+ cause: cause || input
127
+ });
128
+ if (hasProp(input, "stack")) {
129
+ try {
130
+ Object.defineProperty(err, "stack", {
131
+ get() {
132
+ return input.stack;
330
133
  }
331
134
  });
332
- }
333
- if (query && query.method) {
334
- delete query.method;
335
- }
336
- return {
337
- namespaceName,
338
- serviceName,
339
- methodName,
340
- actionName,
341
- raw: normalizedUri,
342
- parts: [namespaceName, serviceName, methodName, actionName],
343
- routerParams: {},
344
- query,
345
- uri: baseUri
346
- };
347
- }
348
- const routeTemplate = typeof template === "string" ? template : template.pattern;
349
- const validators = typeof template === "string" ? void 0 : template.validators;
350
- const routerParams = {};
351
- const templateParts = routeTemplate.split("/").filter(Boolean);
352
- const paramValues = parameters;
353
- let valueIndex = 0;
354
- templateParts.forEach((part) => {
355
- if (part.startsWith(":")) {
356
- const paramName = part.substring(1);
357
- const paramValue = paramValues[valueIndex];
358
- if (validators?.[paramName] && paramValue) {
359
- if (!validators[paramName](paramValue)) {
360
- throw ErrorFactory.create({
361
- message: "Invalid value for parameter",
362
- httpStatus: HttpStatus.UNPROCESSABLE_ENTITY,
363
- context: {
364
- uri,
365
- paramName,
366
- paramValue,
367
- validatorName: paramName
368
- }
369
- });
370
- }
135
+ } catch {
136
+ try {
137
+ err.stack = input.stack;
138
+ } catch {
371
139
  }
372
- routerParams[paramName] = paramValue || void 0;
373
- valueIndex++;
374
- } else if (part && part === paramValues[valueIndex]) {
375
- valueIndex++;
376
- }
377
- });
378
- return {
379
- namespaceName,
380
- serviceName,
381
- methodName,
382
- actionName,
383
- raw: normalizedUri,
384
- parts: [namespaceName, serviceName, methodName, actionName],
385
- routerParams,
386
- query: method ? void 0 : query,
387
- uri: baseUri
388
- };
389
- }
390
-
391
- async function findAction(silgi, uri) {
392
- const { parts } = parseURI(uri, silgi.uris);
393
- let result = silgi.services;
394
- for (const part of parts) {
395
- if (result && Object.prototype.hasOwnProperty.call(result, part)) {
396
- result = Object.assign({}, result[part]);
397
- } else {
398
- silgi.logger.fail("Action not found:", `${parts.join("/")}`);
399
- continue;
400
140
  }
401
141
  }
402
- return result;
403
- }
404
- async function scanAction(silgi) {
405
- for (const [key, _value] of Object.entries(silgi.uris)) {
406
- const segments = key.split("/").filter(Boolean);
407
- if (segments.length !== 4) {
408
- console.error(`Invalid URI format for key "${key}". URI must have exactly 4 segments in format: namespace/service/method/action`);
409
- continue;
410
- }
411
- const [namespace, service, method, action] = segments;
412
- if (!namespace || !service || !method || !action) {
413
- console.error(`Invalid URI segments for key "${key}". All segments must be non-empty`);
414
- continue;
415
- }
416
- const handler = await findAction(silgi, key);
417
- silgi.scannedHandlers.set(key, handler);
142
+ if (input.data) {
143
+ err.data = input.data;
144
+ }
145
+ const statusCode = input.statusCode ?? input.status ?? cause?.statusCode ?? cause?.status;
146
+ if (typeof statusCode === "number") {
147
+ err.statusCode = sanitizeStatusCode(statusCode);
418
148
  }
149
+ const statusMessage = input.statusMessage ?? input.statusText ?? cause?.statusMessage ?? cause?.statusText;
150
+ if (statusMessage) {
151
+ err.statusMessage = sanitizeStatusMessage(statusMessage);
152
+ }
153
+ const fatal = input.fatal ?? cause?.fatal;
154
+ if (fatal !== void 0) {
155
+ err.fatal = fatal;
156
+ }
157
+ const unhandled = input.unhandled ?? cause?.unhandled;
158
+ if (unhandled !== void 0) {
159
+ err.unhandled = unhandled;
160
+ }
161
+ return err;
162
+ }
163
+ function isError(input) {
164
+ return input?.constructor?.__silgi_error__ === true;
419
165
  }
420
166
 
421
167
  function replaceRuntimeValues(obj, runtime) {
@@ -463,7 +209,7 @@ function useSilgiStorage(base = "/memory:cache") {
463
209
  }
464
210
  async function generateStorageKey(params) {
465
211
  const {
466
- operation,
212
+ url,
467
213
  input,
468
214
  keyGenerator,
469
215
  requestId,
@@ -473,18 +219,16 @@ async function generateStorageKey(params) {
473
219
  const parts = [
474
220
  cacheScopePrefix,
475
221
  // Always include scope prefix first
476
- operation.namespaceName,
477
- operation.serviceName,
478
- operation.methodName
222
+ url.raw
479
223
  ].filter(Boolean);
480
224
  if (storageOptions?.scope === "request") {
481
225
  if (!requestId) {
482
- throw ErrorFactory.create({
483
- code: HttpStatus.BAD_REQUEST,
484
- message: "Request ID is required for request-scoped cache",
485
- context: {
226
+ throw createError({
227
+ statusCode: 400,
228
+ statusMessage: "Request ID is required for request-scoped cache",
229
+ data: {
486
230
  requestId,
487
- operation,
231
+ url,
488
232
  input,
489
233
  storageOptions,
490
234
  keyGenerator
@@ -515,12 +259,11 @@ async function runSilgiPlugins(silgi) {
515
259
  async function createSilgi(config) {
516
260
  const hooks = createHooks();
517
261
  const silgi = {
518
- schemas: config.schemas,
262
+ router: void 0,
263
+ routerPrefixs: [],
264
+ schemas: config.schemas ?? {},
519
265
  services: config.services ?? {},
520
266
  shared: config.shared ?? void 0,
521
- uris: config.uris ?? {},
522
- modulesURIs: config.modulesURIs ?? {},
523
- scannedHandlers: /* @__PURE__ */ new Map(),
524
267
  plugins: config.plugins ?? [],
525
268
  framework: config.framework ?? void 0,
526
269
  storage: config.options.putStorage ?? void 0,
@@ -538,15 +281,40 @@ async function createSilgi(config) {
538
281
  tag: "silgi"
539
282
  })).withTag("silgi"),
540
283
  captureError: config.captureError ?? (() => {
541
- }),
542
- routeRules: void 0
284
+ })
543
285
  };
544
- const routeRules = createRouteRules();
545
- routeRules.importRules(config.options.routeRules ?? {});
546
- silgi.routeRules = routeRules;
286
+ if (!silgi.router) {
287
+ silgi.router = createRouter();
288
+ }
289
+ for (const route in silgi.services) {
290
+ const routeParts = route.split("/").filter(Boolean);
291
+ if (routeParts.length > 0) {
292
+ const prefix = `/${routeParts[0]}`;
293
+ if (!silgi.routerPrefixs.includes(prefix)) {
294
+ silgi.routerPrefixs.push(prefix);
295
+ }
296
+ }
297
+ const methods = silgi.services[route];
298
+ for (const method in methods) {
299
+ const methodObject = methods[method];
300
+ if (methodObject) {
301
+ const _method = (method || "").toUpperCase();
302
+ const schemaWrapper = silgi.schemas?.[route]?.[method];
303
+ if (!schemaWrapper) {
304
+ silgi.logger.warn(`Schema not found for ${route}`);
305
+ continue;
306
+ }
307
+ addRoute(silgi.router, _method, route, {
308
+ method: _method,
309
+ route,
310
+ setup: methodObject,
311
+ schema: schemaWrapper
312
+ });
313
+ }
314
+ }
315
+ }
547
316
  silgi.hooks.addHooks(silgi.options.hooks);
548
317
  await runSilgiPlugins(silgi);
549
- await scanAction(silgi);
550
318
  if (!silgi.storage) {
551
319
  silgi.storage = await createStorage(silgi);
552
320
  }
@@ -569,79 +337,275 @@ async function createSilgi(config) {
569
337
  return silgi;
570
338
  }
571
339
 
572
- function silgi(event) {
340
+ class _SilgiEvent {
341
+ static __is_event__ = true;
342
+ req;
343
+ url;
344
+ context;
345
+ _res;
346
+ constructor(req, context) {
347
+ this.context = context || new EmptyObject();
348
+ this.req = req;
349
+ const _url = req._url;
350
+ this.url = _url && _url instanceof URL ? _url : new FastURL(req.url);
351
+ }
352
+ get res() {
353
+ if (!this._res) {
354
+ this._res = new SilgiEventResponse();
355
+ }
356
+ return this._res;
357
+ }
358
+ toString() {
359
+ return `[${this.req.method}] ${this.req.url}`;
360
+ }
361
+ toJSON() {
362
+ return this.toString();
363
+ }
364
+ }
365
+ class SilgiEventResponse {
366
+ status;
367
+ // statusText?: string;
368
+ _headers;
369
+ get headers() {
370
+ if (!this._headers) {
371
+ this._headers = new Headers();
372
+ }
373
+ return this._headers;
374
+ }
375
+ }
376
+
377
+ async function parseRequestInput(req) {
378
+ const contentType = req.headers.get("content-type") || "";
379
+ if (contentType.startsWith("application/json")) {
380
+ const text = await req.text();
381
+ if (!text)
382
+ return void 0;
383
+ return JSON.parse(text);
384
+ }
385
+ if (contentType.startsWith("text/")) {
386
+ return await req.text();
387
+ }
388
+ if (contentType.startsWith("application/octet-stream")) {
389
+ return new File([await req.arrayBuffer()], "uploaded.bin", { type: contentType });
390
+ }
391
+ return await req.text();
392
+ }
393
+ function wrapBodyAndContentType(options) {
394
+ let { body, headers } = options;
395
+ const setContentType = (type) => {
396
+ if (!headers)
397
+ headers = {};
398
+ if (headers instanceof Headers) {
399
+ if (!headers.has("Content-Type"))
400
+ headers.set("Content-Type", type);
401
+ } else if (Array.isArray(headers)) {
402
+ if (!headers.some(([k]) => k.toLowerCase() === "content-type")) {
403
+ headers.push(["Content-Type", type]);
404
+ }
405
+ } else {
406
+ if (!("content-type" in headers)) {
407
+ headers["Content-Type"] = type;
408
+ }
409
+ }
410
+ };
411
+ if (typeof File !== "undefined" && body instanceof File) {
412
+ body = new Blob([body], { type: body.type });
413
+ setContentType(body.type || "application/octet-stream");
414
+ } else if (body instanceof Blob) {
415
+ setContentType(body.type || "application/octet-stream");
416
+ } else if (body && typeof body === "object") {
417
+ body = new Blob([JSON.stringify(body)], { type: "application/json" });
418
+ setContentType("application/json");
419
+ } else if (typeof body === "string") {
420
+ body = new Blob([body], { type: "text/plain" });
421
+ setContentType("text/plain");
422
+ }
423
+ return { body, headers };
424
+ }
425
+
426
+ const plusRegex = /\+/g;
427
+ function parseQuery(input) {
428
+ const params = new EmptyObject();
429
+ if (!input || input === "?") {
430
+ return params;
431
+ }
432
+ const inputLength = input.length;
433
+ let key = "";
434
+ let value = "";
435
+ let startingIndex = -1;
436
+ let equalityIndex = -1;
437
+ let shouldDecodeKey = false;
438
+ let shouldDecodeValue = false;
439
+ let keyHasPlus = false;
440
+ let valueHasPlus = false;
441
+ let hasBothKeyValuePair = false;
442
+ let c = 0;
443
+ for (let i = 0; i < inputLength + 1; i++) {
444
+ c = i === inputLength ? 38 : input.charCodeAt(i);
445
+ switch (c) {
446
+ case 38: {
447
+ hasBothKeyValuePair = equalityIndex > startingIndex;
448
+ if (!hasBothKeyValuePair) {
449
+ equalityIndex = i;
450
+ }
451
+ key = input.slice(startingIndex + 1, equalityIndex);
452
+ if (hasBothKeyValuePair || key.length > 0) {
453
+ if (keyHasPlus) {
454
+ key = key.replace(plusRegex, " ");
455
+ }
456
+ if (shouldDecodeKey) {
457
+ try {
458
+ key = decodeURIComponent(key);
459
+ } catch {
460
+ }
461
+ }
462
+ if (hasBothKeyValuePair) {
463
+ value = input.slice(equalityIndex + 1, i);
464
+ if (valueHasPlus) {
465
+ value = value.replace(plusRegex, " ");
466
+ }
467
+ if (shouldDecodeValue) {
468
+ try {
469
+ value = decodeURIComponent(value);
470
+ } catch {
471
+ }
472
+ }
473
+ }
474
+ const currentValue = params[key];
475
+ if (currentValue === void 0) {
476
+ params[key] = value;
477
+ } else {
478
+ if (Array.isArray(currentValue)) {
479
+ currentValue.push(value);
480
+ } else {
481
+ params[key] = [currentValue, value];
482
+ }
483
+ }
484
+ }
485
+ value = "";
486
+ startingIndex = i;
487
+ equalityIndex = i;
488
+ shouldDecodeKey = false;
489
+ shouldDecodeValue = false;
490
+ keyHasPlus = false;
491
+ valueHasPlus = false;
492
+ break;
493
+ }
494
+ case 61: {
495
+ if (equalityIndex <= startingIndex) {
496
+ equalityIndex = i;
497
+ } else {
498
+ shouldDecodeValue = true;
499
+ }
500
+ break;
501
+ }
502
+ case 43: {
503
+ if (equalityIndex > startingIndex) {
504
+ valueHasPlus = true;
505
+ } else {
506
+ keyHasPlus = true;
507
+ }
508
+ break;
509
+ }
510
+ case 37: {
511
+ if (equalityIndex > startingIndex) {
512
+ shouldDecodeValue = true;
513
+ } else {
514
+ shouldDecodeKey = true;
515
+ }
516
+ break;
517
+ }
518
+ }
519
+ }
520
+ return params;
521
+ }
522
+
523
+ function getQuery(event) {
524
+ return parseQuery(event.url.search.slice(1));
525
+ }
526
+ function getRouterParams(event, opts = {}) {
527
+ let params = event.context.params || {};
528
+ if (opts.decode) {
529
+ params = { ...params };
530
+ for (const key in params) {
531
+ params[key] = decodeURIComponent(params[key]);
532
+ }
533
+ }
534
+ return params;
535
+ }
536
+
537
+ function createRoute(params) {
573
538
  return {
574
- execute: (uriString, input, source, queryParams) => {
575
- return execute(uriString, input, event, source, queryParams);
539
+ [params.route]: {
540
+ ...params
576
541
  }
577
542
  };
578
543
  }
579
- async function execute(uriString, input, event, source, queryParams) {
580
- const silgiCtx = useSilgi();
581
- const config = {
582
- returnNull: false
544
+ function getUrlPrefix(path, method) {
545
+ const parse = path.includes("://") ? new FastURL(path) : new URL(path, "http://localhost");
546
+ const cleanedPath = parse.pathname + parse.search + parse.hash;
547
+ const segments = cleanedPath.split("/").filter(Boolean);
548
+ if (segments.length < 2) {
549
+ throw createError({
550
+ statusCode: 400,
551
+ statusMessage: "Invalid URL format",
552
+ data: { cleanedPath }
553
+ });
554
+ }
555
+ const prefix = `/${segments[0]}`;
556
+ const namespace = segments[1];
557
+ return {
558
+ namespaceName: namespace,
559
+ prefixName: prefix,
560
+ raw: path,
561
+ path: cleanedPath,
562
+ methodName: method || "GET"
583
563
  };
564
+ }
565
+
566
+ async function orchestrate(route, event) {
567
+ const input = await parseRequestInput(event.req);
568
+ const silgiCtx = useSilgi();
569
+ const silgiURL = getUrlPrefix(route.route, event.req.method);
584
570
  try {
585
- const operation = parseURI(uriString, silgiCtx.uris);
586
- if (!operation) {
587
- throw ErrorFactory.create({ message: "Invalid URI", httpStatus: HttpStatus.BAD_REQUEST });
588
- }
571
+ const routerParams = getRouterParams(event);
572
+ const queryParams = getQuery(event);
589
573
  let success = false;
590
574
  let cached = false;
591
575
  let result;
592
- const handler = silgiCtx.scannedHandlers.get(operation.uri);
593
- if (!handler) {
594
- throw ErrorFactory.create({
595
- message: "execute not found",
596
- httpStatus: HttpStatus.NOT_FOUND,
597
- context: {
598
- uri: uriString
599
- }
600
- });
601
- }
602
- await silgiCtx.callHook("execute:before", {
603
- operation,
604
- input,
605
- event,
606
- modules: handler.modules,
607
- source,
608
- config
609
- });
610
- if (config.returnNull) {
611
- return result;
612
- }
613
- const cacheData = await cacheExecute(input, operation, handler, event);
576
+ const setup = route.setup;
577
+ const cacheData = await cacheExecute(input, route, silgiURL, event);
614
578
  if (cacheData?.success) {
615
579
  result = cacheData.data;
616
580
  success = cacheData.success;
617
581
  cached = cacheData.cached;
618
582
  } else {
619
- let parameters = defu(operation.routerParams, operation.query) || {};
620
- if (queryParams) {
621
- parameters = defu(queryParams, parameters);
622
- }
623
- silgiCtx.shared.silgi = silgi(event);
624
- result = await handler?.handler(
625
- defu(input, { parameters }),
583
+ silgiCtx.shared.$fetch = silgiFetch;
584
+ result = await setup?.handler(
585
+ {
586
+ args: input,
587
+ parameters: {
588
+ query: queryParams,
589
+ path: routerParams
590
+ }
591
+ },
626
592
  silgiCtx.shared,
627
593
  event,
628
- source
594
+ event.context.source
629
595
  );
630
596
  success = true;
631
597
  }
632
598
  await silgiCtx.callHook("execute:after", {
633
- operation,
599
+ url: silgiURL,
634
600
  input,
635
601
  event,
636
602
  result,
637
603
  success,
638
- source,
639
- modules: handler.modules,
640
- config
604
+ modules: setup.modules
641
605
  });
642
606
  if (!cached) {
643
- if (success && cacheData?.cachedKey && handler.storage) {
644
- await useSilgiStorage(handler.storage.base).setItem(cacheData.cachedKey, result, handler.storage.options);
607
+ if (success && cacheData?.cachedKey && setup.storage) {
608
+ await useSilgiStorage(setup.storage.base).setItem(cacheData.cachedKey, result, setup.storage.options);
645
609
  }
646
610
  }
647
611
  return result;
@@ -649,30 +613,38 @@ async function execute(uriString, input, event, source, queryParams) {
649
613
  await silgiCtx.callHook("execute:error", {
650
614
  input,
651
615
  event,
652
- source,
653
616
  error: err instanceof Error ? err : new Error(String(err)),
654
- timestamp: Date.now(),
655
- config
656
- });
657
- silgiCtx.captureError(silgiCtx, SilgiError.from(err), {
658
- event,
659
- tags: ["execute"]
617
+ url: silgiURL
660
618
  });
619
+ silgiCtx.captureError(
620
+ silgiCtx,
621
+ createError({
622
+ message: err instanceof Error ? err.message : String(err),
623
+ statusCode: 500,
624
+ statusMessage: "Internal Server Error",
625
+ cause: err
626
+ }),
627
+ {
628
+ event,
629
+ tags: ["execute"]
630
+ }
631
+ );
661
632
  throw err;
662
633
  }
663
634
  }
664
- async function cacheExecute(input, operation, handler, event) {
665
- if (!handler.storage)
635
+ async function cacheExecute(input, route, silgiURL, event) {
636
+ const setup = route.setup;
637
+ if (!setup.storage)
666
638
  return;
667
- const cacheKey = handler.storage ? await generateStorageKey({
668
- operation,
639
+ const cacheKey = setup.storage ? await generateStorageKey({
640
+ url: silgiURL,
669
641
  input,
670
- keyGenerator: handler.storage.key,
671
- storageOptions: handler.storage,
642
+ keyGenerator: setup.storage.key,
643
+ storageOptions: setup.storage,
672
644
  requestId: event?.requestId
673
645
  }) : null;
674
646
  if (cacheKey) {
675
- const cachedResult = await useSilgiStorage(handler.storage.base).getItem(cacheKey);
647
+ const cachedResult = await useSilgiStorage(setup.storage.base).getItem(cacheKey);
676
648
  if (cachedResult !== null) {
677
649
  return {
678
650
  success: true,
@@ -690,32 +662,235 @@ async function cacheExecute(input, operation, handler, event) {
690
662
  };
691
663
  }
692
664
 
693
- function merge(items, maxLevel = 4, currentLevel = 1) {
694
- const arrayItems = Array.isArray(items) ? items : [items];
695
- return arrayItems.reduce((acc, item) => {
696
- if (!item)
697
- return acc;
698
- Object.keys(item).forEach((key) => {
699
- if (typeof item[key] === "object" && item[key] !== null && currentLevel < maxLevel) {
700
- if (!acc[key] || typeof acc[key] !== "object") {
701
- acc[key] = {};
702
- }
703
- acc[key] = merge([acc[key], item[key]], maxLevel, currentLevel + 1);
704
- } else if (acc[key] === void 0) {
705
- acc[key] = item[key];
706
- }
665
+ const kNotFound = /* @__PURE__ */ Symbol.for("silgi.notFound");
666
+ const kHandled = /* @__PURE__ */ Symbol.for("silgi.handled");
667
+ function handleResponse(val, event, config) {
668
+ if (val && val instanceof Promise) {
669
+ return val.catch((error) => error).then((resolvedVal) => handleResponse(resolvedVal, event, config));
670
+ }
671
+ const response = prepareResponse(val, event, config);
672
+ if (response instanceof Promise) {
673
+ return handleResponse(response, event, config);
674
+ }
675
+ const { onBeforeResponse } = config;
676
+ return onBeforeResponse ? Promise.resolve(onBeforeResponse(event, response)).then(() => response) : response;
677
+ }
678
+ function prepareResponse(val, event, config, nested) {
679
+ if (val === kHandled) {
680
+ return new FastResponse(null);
681
+ }
682
+ if (val === kNotFound) {
683
+ val = createError({
684
+ statusCode: 404,
685
+ statusMessage: `Cannot find any route matching [${event.req.method}] ${event.url}`
707
686
  });
708
- return acc;
709
- }, {});
687
+ }
688
+ if (val && val instanceof Error) {
689
+ const error = createError(val);
690
+ const { onError } = config;
691
+ return onError && !nested ? Promise.resolve(onError(error, event)).catch((error2) => error2).then((newVal) => prepareResponse(newVal ?? val, event, config, true)) : errorResponse(error, config.debug);
692
+ }
693
+ const eventHeaders = event.res._headers;
694
+ if (!(val instanceof Response)) {
695
+ const res = prepareResponseBody(val, event, config);
696
+ const status = event.res.status;
697
+ return new FastResponse(
698
+ nullBody(event.req.method, status) ? null : res.body,
699
+ {
700
+ status,
701
+ statusText: event.res.statusText,
702
+ headers: res.headers && eventHeaders ? mergeHeaders(res.headers, eventHeaders) : res.headers || eventHeaders
703
+ }
704
+ );
705
+ }
706
+ if (!eventHeaders) {
707
+ return val;
708
+ }
709
+ return new FastResponse(
710
+ nullBody(event.req.method, val.status) ? null : val.body,
711
+ {
712
+ status: val.status,
713
+ statusText: val.statusText,
714
+ headers: mergeHeaders(eventHeaders, val.headers)
715
+ }
716
+ );
717
+ }
718
+ function nullBody(method, status) {
719
+ return method === "HEAD" || status === 100 || status === 101 || status === 102 || status === 204 || status === 205 || status === 304;
720
+ }
721
+ function mergeHeaders(base, merge) {
722
+ const mergedHeaders = new Headers(base);
723
+ for (const [name, value] of merge) {
724
+ if (name === "set-cookie") {
725
+ mergedHeaders.append(name, value);
726
+ } else {
727
+ mergedHeaders.set(name, value);
728
+ }
729
+ }
730
+ return mergedHeaders;
731
+ }
732
+ const emptyHeaders = new Headers({ "content-length": "0" });
733
+ const jsonHeaders = new Headers({
734
+ "content-type": "application/json;charset=UTF-8"
735
+ });
736
+ function prepareResponseBody(val, event, config) {
737
+ if (val === null || val === void 0) {
738
+ return { body: "", headers: emptyHeaders };
739
+ }
740
+ const valType = typeof val;
741
+ if (valType === "string") {
742
+ return { body: val };
743
+ }
744
+ if (val instanceof Uint8Array) {
745
+ event.res.headers.set("content-length", val.byteLength.toString());
746
+ return { body: val };
747
+ }
748
+ if (isJSONSerializable(val, valType)) {
749
+ return {
750
+ body: JSON.stringify(val, void 0, config.debug ? 2 : void 0),
751
+ headers: jsonHeaders
752
+ };
753
+ }
754
+ if (valType === "bigint") {
755
+ return { body: val.toString(), headers: jsonHeaders };
756
+ }
757
+ if (val instanceof Blob) {
758
+ const headers = {
759
+ "content-type": val.type,
760
+ "content-length": val.size.toString()
761
+ };
762
+ if ("name" in val) {
763
+ const filename = encodeURIComponent(val.name);
764
+ headers["content-disposition"] = `filename="${filename}"; filename*=UTF-8''${filename}`;
765
+ }
766
+ return { body: val.stream(), headers };
767
+ }
768
+ if (valType === "symbol") {
769
+ return { body: val.toString() };
770
+ }
771
+ if (valType === "function") {
772
+ return { body: `${val.name}()` };
773
+ }
774
+ return { body: val };
775
+ }
776
+ function errorResponse(error, debug) {
777
+ return new FastResponse(
778
+ JSON.stringify(
779
+ {
780
+ statusCode: error.statusCode,
781
+ statusMessage: error.statusMessage,
782
+ data: error.data,
783
+ stack: debug && error.stack ? error.stack.split("\n").map((l) => l.trim()) : void 0
784
+ },
785
+ null,
786
+ 2
787
+ ),
788
+ {
789
+ status: error.statusCode,
790
+ statusText: error.statusMessage,
791
+ headers: {
792
+ "content-type": "application/json; charset=utf-8"
793
+ }
794
+ }
795
+ );
796
+ }
797
+
798
+ function getHeader(name, headers) {
799
+ if (!headers) {
800
+ return;
801
+ }
802
+ if (headers instanceof Headers) {
803
+ return headers.get(name);
804
+ }
805
+ const lName = name.toLowerCase();
806
+ if (Array.isArray(headers)) {
807
+ return headers.find(
808
+ (h) => h[0] === name || lName === h[0].toLowerCase()
809
+ )?.[1];
810
+ }
811
+ return headers[name] || headers[lName];
812
+ }
813
+ function substitutePathParams(path, pathParams) {
814
+ if (!pathParams)
815
+ return path;
816
+ return path.replace(/:(\w+)/g, (_, key) => {
817
+ if (key in pathParams) {
818
+ return encodeURIComponent(pathParams[key]);
819
+ }
820
+ return `:${key}`;
821
+ });
710
822
  }
711
- function mergeSchemas(typesOrArray) {
712
- return merge(typesOrArray);
823
+ function createSilgiCore(event) {
824
+ return {
825
+ resolve: async (path, method, context) => {
826
+ const silgiCtx = useSilgi();
827
+ if (!silgiCtx.router) {
828
+ return void 0;
829
+ }
830
+ const routeStr = substitutePathParams(String(path), context?.pathParams);
831
+ const methodStr = String(method);
832
+ const match = findRoute(silgiCtx.router, methodStr, routeStr);
833
+ return match?.data?.setup.h;
834
+ }
835
+ };
713
836
  }
714
- function mergeServices(servicesOrArray) {
715
- return merge(servicesOrArray);
837
+ async function silgiFetch(_request, options, context) {
838
+ let request;
839
+ if (options) {
840
+ const wrapped = wrapBodyAndContentType(options);
841
+ options.body = wrapped.body;
842
+ options.headers = wrapped.headers;
843
+ }
844
+ if (typeof _request === "string") {
845
+ _request = substitutePathParams(_request, options?.pathParams);
846
+ let url = _request;
847
+ if (url[0] === "/") {
848
+ const host = getHeader("Host", options?.headers) || ".";
849
+ const proto = getHeader("X-Forwarded-Proto", options?.headers) === "https" ? "https" : "http";
850
+ url = `${proto}://${host}${url}`;
851
+ }
852
+ request = new Request(url, options);
853
+ } else if (options || _request instanceof URL) {
854
+ request = new Request(_request, options);
855
+ } else {
856
+ request = _request;
857
+ }
858
+ const silgiEvent = new _SilgiEvent(request, context);
859
+ let handlerRes;
860
+ try {
861
+ handlerRes = await handler(silgiEvent);
862
+ } catch (error) {
863
+ handlerRes = Promise.reject(error);
864
+ }
865
+ return handleResponse(handlerRes, silgiEvent, {});
716
866
  }
717
- function mergeShared(sharedOrArray) {
718
- return merge(sharedOrArray, 1, 1);
867
+ async function handler(event) {
868
+ const silgiCtx = useSilgi();
869
+ const pathname = event.url.pathname;
870
+ let _chain = void 0;
871
+ _chain = Promise.resolve(await silgiCtx.callHook("request:on", event));
872
+ if (silgiCtx.router) {
873
+ const match = findRoute(silgiCtx.router, event.req.method, pathname);
874
+ if (match) {
875
+ if (_chain) {
876
+ return _chain.then(async (_previous) => {
877
+ if (_previous !== void 0 && _previous !== kNotFound) {
878
+ return _previous;
879
+ }
880
+ event.context.params = match.params;
881
+ event.context.matchedRoute = match.data;
882
+ return orchestrate(match.data, event);
883
+ });
884
+ } else {
885
+ event.context.params = match.params;
886
+ event.context.matchedRoute = match.data;
887
+ return orchestrate(match.data, event);
888
+ }
889
+ }
890
+ }
891
+ return _chain ? _chain.then(
892
+ (_previous) => _previous === void 0 ? kNotFound : _previous
893
+ ) : kNotFound;
719
894
  }
720
895
 
721
896
  function getEvent(event) {
@@ -735,12 +910,42 @@ function getEventContext(event) {
735
910
  return _event;
736
911
  }
737
912
 
738
- function createSchema(silgiType) {
739
- return silgiType;
913
+ function createSchema(params) {
914
+ const { namespace, prefix, path, methods } = params;
915
+ const routeWithPrefix = `${prefix}${namespace}${path}`;
916
+ return {
917
+ [routeWithPrefix]: methods
918
+ };
919
+ }
920
+
921
+ function deepMerge(target, source) {
922
+ if (typeof target !== "object" || target === null)
923
+ return source;
924
+ if (typeof source !== "object" || source === null)
925
+ return source;
926
+ const result = Array.isArray(target) ? [...target] : { ...target };
927
+ for (const key of Object.keys(source)) {
928
+ if (key in target) {
929
+ result[key] = deepMerge(target[key], source[key]);
930
+ } else {
931
+ result[key] = source[key];
932
+ }
933
+ }
934
+ return result;
935
+ }
936
+ function deepMergeObjects(schemas) {
937
+ let merged = {};
938
+ for (const schema of schemas) {
939
+ merged = deepMerge(merged, schema);
940
+ }
941
+ return merged;
740
942
  }
741
943
 
742
- function createService(variables) {
743
- return variables;
944
+ function createService(params) {
945
+ const { path, methods } = params;
946
+ return {
947
+ [path]: methods
948
+ };
744
949
  }
745
950
 
746
951
  function createShared(shared) {
@@ -766,4 +971,4 @@ const autoImportTypes = [
766
971
  "ExtractQueryParamsFromURI"
767
972
  ];
768
973
 
769
- export { ErrorCategory, ErrorFactory, ErrorSeverity, HttpStatus, SilgiError, autoImportTypes, createSchema, createService, createShared, createSilgi, createStorage, getEvent, getEventContext, isBaseError, mergeSchemas, mergeServices, mergeShared, parseURI, replaceRuntimeValues, silgi, silgiCtx, storageMount, tryUseSilgi, useSilgi, useSilgiStorage };
974
+ export { SilgiError, autoImportTypes, createError, createRoute, createSchema, createService, createShared, createSilgi, createSilgiCore, createStorage, deepMergeObjects, getEvent, getEventContext, handleResponse, isError, replaceRuntimeValues, silgiCtx, silgiFetch, storageMount, tryUseSilgi, useSilgi, useSilgiStorage };