silgi 0.24.15 → 0.24.17

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.
Files changed (91) hide show
  1. package/dist/cli/build/prepare.mjs +43 -0
  2. package/dist/cli/{dev.mjs → commands/dev.mjs} +4 -43
  3. package/dist/cli/commands/env.mjs +40 -0
  4. package/dist/cli/{install.mjs → commands/install.mjs} +3 -37
  5. package/dist/cli/commands/prepare.mjs +66 -0
  6. package/dist/cli/{prepare.mjs → commands/run.mjs} +9 -82
  7. package/dist/cli/config/defaults.mjs +129 -0
  8. package/dist/cli/config/index.mjs +2 -16
  9. package/dist/cli/config/loader.mjs +97 -0
  10. package/dist/cli/config/resolvers/compatibility.mjs +90 -0
  11. package/dist/cli/config/resolvers/imports.mjs +96 -0
  12. package/dist/cli/config/resolvers/paths.mjs +167 -0
  13. package/dist/cli/config/resolvers/storage.mjs +25 -0
  14. package/dist/cli/config/resolvers/url.mjs +7 -0
  15. package/dist/cli/config/types.mjs +191 -0
  16. package/dist/cli/core/app.mjs +92 -0
  17. package/dist/cli/core/devServer.mjs +8 -0
  18. package/dist/cli/core/env.mjs +76 -0
  19. package/dist/cli/core/installPackage.mjs +31 -0
  20. package/dist/cli/core/prepare.mjs +7 -0
  21. package/dist/cli/core/runtimeConfig.mjs +14 -0
  22. package/dist/cli/core/scan.mjs +39 -0
  23. package/dist/cli/core/silgi.mjs +125 -0
  24. package/dist/cli/core/templates.mjs +31 -0
  25. package/dist/cli/framework/emptyFramework.mjs +9 -0
  26. package/dist/cli/framework/h3.mjs +89 -0
  27. package/dist/cli/framework/index.mjs +8 -0
  28. package/dist/cli/framework/nitro.mjs +106 -0
  29. package/dist/cli/framework/nuxt.mjs +9 -0
  30. package/dist/cli/index.mjs +6 -9
  31. package/dist/cli/module/exportScan.mjs +130 -0
  32. package/dist/cli/module/install.mjs +59 -0
  33. package/dist/cli/module/scan.mjs +227 -0
  34. package/dist/cli/scan/commands.mjs +47 -0
  35. package/dist/cli/scan/prepareConfigs.mjs +46 -0
  36. package/dist/cli/scan/prepareCoreFile.mjs +166 -0
  37. package/dist/cli/scan/prepareFramework.mjs +73 -0
  38. package/dist/cli/scan/prepareSchema.mjs +177 -0
  39. package/dist/cli/scan/prepareServerFiles.mjs +119 -0
  40. package/dist/cli/scan/scanExportFile.mjs +155 -0
  41. package/dist/cli/scan/writeCoreFile.mjs +34 -0
  42. package/dist/cli/scan/writeScanFiles.mjs +30 -0
  43. package/dist/cli/scan/writeTypesAndFiles.mjs +109 -0
  44. package/dist/cli/utils/build-uri-map.mjs +39 -0
  45. package/dist/cli/utils/common.mjs +13 -0
  46. package/dist/cli/{compatibility.mjs → utils/compatibility.mjs} +1 -1
  47. package/dist/cli/utils/generateRouterDTS.mjs +80 -0
  48. package/dist/cli/utils/ignore.mjs +46 -0
  49. package/dist/cli/utils/parser.mjs +168 -0
  50. package/dist/cli/utils/readScanFile.mjs +79 -0
  51. package/dist/cli/utils/storage.mjs +25 -0
  52. package/dist/core/createSilgi.mjs +76 -0
  53. package/dist/core/error.mjs +227 -0
  54. package/dist/core/index.mjs +8 -0
  55. package/dist/core/routeRules.mjs +288 -0
  56. package/dist/core/silgi.mjs +128 -0
  57. package/dist/core/silgiApp.mjs +25 -0
  58. package/dist/core/storage.mjs +15 -0
  59. package/dist/core/unctx.mjs +27 -0
  60. package/dist/core/uris/uri.mjs +33 -0
  61. package/dist/core/uris/utils.mjs +130 -0
  62. package/dist/core/utils/event.mjs +15 -0
  63. package/dist/core/utils/merge.mjs +29 -0
  64. package/dist/core/utils/runtime.mjs +22 -0
  65. package/dist/core/utils/schema.mjs +5 -0
  66. package/dist/core/utils/service.mjs +5 -0
  67. package/dist/core/utils/shared.mjs +5 -0
  68. package/dist/core/utils/storage.mjs +72 -0
  69. package/dist/index.mjs +20 -793
  70. package/dist/kit/errors.mjs +11 -0
  71. package/dist/kit/esm.mjs +14 -0
  72. package/dist/kit/fs.mjs +30 -0
  73. package/dist/kit/gen.mjs +44 -0
  74. package/dist/kit/hash.mjs +8 -0
  75. package/dist/kit/index.mjs +15 -528
  76. package/dist/kit/isFramework.mjs +25 -0
  77. package/dist/kit/logger.mjs +7 -0
  78. package/dist/kit/module.mjs +73 -0
  79. package/dist/kit/parseServices.mjs +57 -0
  80. package/dist/kit/path.mjs +34 -0
  81. package/dist/kit/preset.mjs +6 -0
  82. package/dist/kit/resolve.mjs +80 -0
  83. package/dist/kit/template.mjs +49 -0
  84. package/dist/kit/useRequest.mjs +91 -0
  85. package/dist/kit/utils.mjs +43 -0
  86. package/dist/package.json.mjs +5 -0
  87. package/dist/types/index.d.mts +1 -1
  88. package/package.json +1 -1
  89. package/dist/_chunks/silgiApp.mjs +0 -2682
  90. package/dist/cli/types.mjs +0 -772
  91. /package/dist/cli/{init.mjs → commands/init.mjs} +0 -0
@@ -0,0 +1,227 @@
1
+ var HttpStatus = /* @__PURE__ */ ((HttpStatus2) => {
2
+ HttpStatus2[HttpStatus2["CONTINUE"] = 100] = "CONTINUE";
3
+ HttpStatus2[HttpStatus2["SWITCHING_PROTOCOLS"] = 101] = "SWITCHING_PROTOCOLS";
4
+ HttpStatus2[HttpStatus2["PROCESSING"] = 102] = "PROCESSING";
5
+ HttpStatus2[HttpStatus2["EARLY_HINTS"] = 103] = "EARLY_HINTS";
6
+ HttpStatus2[HttpStatus2["OK"] = 200] = "OK";
7
+ HttpStatus2[HttpStatus2["CREATED"] = 201] = "CREATED";
8
+ HttpStatus2[HttpStatus2["ACCEPTED"] = 202] = "ACCEPTED";
9
+ HttpStatus2[HttpStatus2["NON_AUTHORITATIVE_INFORMATION"] = 203] = "NON_AUTHORITATIVE_INFORMATION";
10
+ HttpStatus2[HttpStatus2["NO_CONTENT"] = 204] = "NO_CONTENT";
11
+ HttpStatus2[HttpStatus2["RESET_CONTENT"] = 205] = "RESET_CONTENT";
12
+ HttpStatus2[HttpStatus2["PARTIAL_CONTENT"] = 206] = "PARTIAL_CONTENT";
13
+ HttpStatus2[HttpStatus2["MULTI_STATUS"] = 207] = "MULTI_STATUS";
14
+ HttpStatus2[HttpStatus2["ALREADY_REPORTED"] = 208] = "ALREADY_REPORTED";
15
+ HttpStatus2[HttpStatus2["IM_USED"] = 226] = "IM_USED";
16
+ HttpStatus2[HttpStatus2["MULTIPLE_CHOICES"] = 300] = "MULTIPLE_CHOICES";
17
+ HttpStatus2[HttpStatus2["MOVED_PERMANENTLY"] = 301] = "MOVED_PERMANENTLY";
18
+ HttpStatus2[HttpStatus2["FOUND"] = 302] = "FOUND";
19
+ HttpStatus2[HttpStatus2["SEE_OTHER"] = 303] = "SEE_OTHER";
20
+ HttpStatus2[HttpStatus2["NOT_MODIFIED"] = 304] = "NOT_MODIFIED";
21
+ HttpStatus2[HttpStatus2["USE_PROXY"] = 305] = "USE_PROXY";
22
+ HttpStatus2[HttpStatus2["TEMPORARY_REDIRECT"] = 307] = "TEMPORARY_REDIRECT";
23
+ HttpStatus2[HttpStatus2["PERMANENT_REDIRECT"] = 308] = "PERMANENT_REDIRECT";
24
+ HttpStatus2[HttpStatus2["BAD_REQUEST"] = 400] = "BAD_REQUEST";
25
+ HttpStatus2[HttpStatus2["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
26
+ HttpStatus2[HttpStatus2["PAYMENT_REQUIRED"] = 402] = "PAYMENT_REQUIRED";
27
+ HttpStatus2[HttpStatus2["FORBIDDEN"] = 403] = "FORBIDDEN";
28
+ HttpStatus2[HttpStatus2["NOT_FOUND"] = 404] = "NOT_FOUND";
29
+ HttpStatus2[HttpStatus2["METHOD_NOT_ALLOWED"] = 405] = "METHOD_NOT_ALLOWED";
30
+ HttpStatus2[HttpStatus2["NOT_ACCEPTABLE"] = 406] = "NOT_ACCEPTABLE";
31
+ HttpStatus2[HttpStatus2["PROXY_AUTHENTICATION_REQUIRED"] = 407] = "PROXY_AUTHENTICATION_REQUIRED";
32
+ HttpStatus2[HttpStatus2["REQUEST_TIMEOUT"] = 408] = "REQUEST_TIMEOUT";
33
+ HttpStatus2[HttpStatus2["CONFLICT"] = 409] = "CONFLICT";
34
+ HttpStatus2[HttpStatus2["GONE"] = 410] = "GONE";
35
+ HttpStatus2[HttpStatus2["LENGTH_REQUIRED"] = 411] = "LENGTH_REQUIRED";
36
+ HttpStatus2[HttpStatus2["PRECONDITION_FAILED"] = 412] = "PRECONDITION_FAILED";
37
+ HttpStatus2[HttpStatus2["PAYLOAD_TOO_LARGE"] = 413] = "PAYLOAD_TOO_LARGE";
38
+ HttpStatus2[HttpStatus2["URI_TOO_LONG"] = 414] = "URI_TOO_LONG";
39
+ HttpStatus2[HttpStatus2["UNSUPPORTED_MEDIA_TYPE"] = 415] = "UNSUPPORTED_MEDIA_TYPE";
40
+ HttpStatus2[HttpStatus2["RANGE_NOT_SATISFIABLE"] = 416] = "RANGE_NOT_SATISFIABLE";
41
+ HttpStatus2[HttpStatus2["EXPECTATION_FAILED"] = 417] = "EXPECTATION_FAILED";
42
+ HttpStatus2[HttpStatus2["IM_A_TEAPOT"] = 418] = "IM_A_TEAPOT";
43
+ HttpStatus2[HttpStatus2["MISDIRECTED_REQUEST"] = 421] = "MISDIRECTED_REQUEST";
44
+ HttpStatus2[HttpStatus2["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
45
+ HttpStatus2[HttpStatus2["LOCKED"] = 423] = "LOCKED";
46
+ HttpStatus2[HttpStatus2["FAILED_DEPENDENCY"] = 424] = "FAILED_DEPENDENCY";
47
+ HttpStatus2[HttpStatus2["TOO_EARLY"] = 425] = "TOO_EARLY";
48
+ HttpStatus2[HttpStatus2["UPGRADE_REQUIRED"] = 426] = "UPGRADE_REQUIRED";
49
+ HttpStatus2[HttpStatus2["PRECONDITION_REQUIRED"] = 428] = "PRECONDITION_REQUIRED";
50
+ HttpStatus2[HttpStatus2["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS";
51
+ HttpStatus2[HttpStatus2["REQUEST_HEADER_FIELDS_TOO_LARGE"] = 431] = "REQUEST_HEADER_FIELDS_TOO_LARGE";
52
+ HttpStatus2[HttpStatus2["UNAVAILABLE_FOR_LEGAL_REASONS"] = 451] = "UNAVAILABLE_FOR_LEGAL_REASONS";
53
+ HttpStatus2[HttpStatus2["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
54
+ HttpStatus2[HttpStatus2["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED";
55
+ HttpStatus2[HttpStatus2["BAD_GATEWAY"] = 502] = "BAD_GATEWAY";
56
+ HttpStatus2[HttpStatus2["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE";
57
+ HttpStatus2[HttpStatus2["GATEWAY_TIMEOUT"] = 504] = "GATEWAY_TIMEOUT";
58
+ HttpStatus2[HttpStatus2["HTTP_VERSION_NOT_SUPPORTED"] = 505] = "HTTP_VERSION_NOT_SUPPORTED";
59
+ HttpStatus2[HttpStatus2["VARIANT_ALSO_NEGOTIATES"] = 506] = "VARIANT_ALSO_NEGOTIATES";
60
+ HttpStatus2[HttpStatus2["INSUFFICIENT_STORAGE"] = 507] = "INSUFFICIENT_STORAGE";
61
+ HttpStatus2[HttpStatus2["LOOP_DETECTED"] = 508] = "LOOP_DETECTED";
62
+ HttpStatus2[HttpStatus2["NOT_EXTENDED"] = 510] = "NOT_EXTENDED";
63
+ HttpStatus2[HttpStatus2["NETWORK_AUTHENTICATION_REQUIRED"] = 511] = "NETWORK_AUTHENTICATION_REQUIRED";
64
+ return HttpStatus2;
65
+ })(HttpStatus || {});
66
+ var ErrorSeverity = /* @__PURE__ */ ((ErrorSeverity2) => {
67
+ ErrorSeverity2["DEBUG"] = "DEBUG";
68
+ ErrorSeverity2["INFO"] = "INFO";
69
+ ErrorSeverity2["WARNING"] = "WARNING";
70
+ ErrorSeverity2["ERROR"] = "ERROR";
71
+ ErrorSeverity2["CRITICAL"] = "CRITICAL";
72
+ return ErrorSeverity2;
73
+ })(ErrorSeverity || {});
74
+ var ErrorCategory = /* @__PURE__ */ ((ErrorCategory2) => {
75
+ ErrorCategory2["AUTHENTICATION"] = "auth";
76
+ ErrorCategory2["AUTHORIZATION"] = "authorization";
77
+ ErrorCategory2["VALIDATION"] = "validation";
78
+ ErrorCategory2["BUSINESS"] = "business";
79
+ ErrorCategory2["INFRASTRUCTURE"] = "infrastructure";
80
+ ErrorCategory2["EXTERNAL"] = "external";
81
+ ErrorCategory2["UNKNOWN"] = "unknown";
82
+ return ErrorCategory2;
83
+ })(ErrorCategory || {});
84
+ class ErrorFactory {
85
+ static createMetadata(metadata) {
86
+ return {
87
+ timestamp: Date.now(),
88
+ ...metadata
89
+ };
90
+ }
91
+ static create(options) {
92
+ return new SilgiError({
93
+ code: options.code ?? options.httpStatus ?? 500 /* INTERNAL_SERVER_ERROR */,
94
+ message: options.message,
95
+ category: options.category ?? "unknown" /* UNKNOWN */,
96
+ severity: options.severity ?? "ERROR" /* ERROR */,
97
+ httpStatus: options.httpStatus ?? 500 /* INTERNAL_SERVER_ERROR */,
98
+ metadata: this.createMetadata(options.metadata),
99
+ cause: options.cause,
100
+ context: options.context
101
+ });
102
+ }
103
+ // Predefined error creators
104
+ static authenticationError(message, context) {
105
+ return this.create({
106
+ message,
107
+ code: 401,
108
+ category: "auth" /* AUTHENTICATION */,
109
+ severity: "ERROR" /* ERROR */,
110
+ httpStatus: 401 /* UNAUTHORIZED */,
111
+ context
112
+ });
113
+ }
114
+ static authorizationError(message, context) {
115
+ return this.create({
116
+ message,
117
+ code: 403,
118
+ category: "authorization" /* AUTHORIZATION */,
119
+ severity: "ERROR" /* ERROR */,
120
+ httpStatus: 403 /* FORBIDDEN */,
121
+ context
122
+ });
123
+ }
124
+ static validationError(message, context) {
125
+ return this.create({
126
+ message,
127
+ code: 400,
128
+ category: "validation" /* VALIDATION */,
129
+ severity: "WARNING" /* WARNING */,
130
+ httpStatus: 400 /* BAD_REQUEST */,
131
+ context
132
+ });
133
+ }
134
+ static notFoundError(message, context) {
135
+ return this.create({
136
+ message,
137
+ code: 404,
138
+ category: "business" /* BUSINESS */,
139
+ severity: "WARNING" /* WARNING */,
140
+ httpStatus: 404 /* NOT_FOUND */,
141
+ context
142
+ });
143
+ }
144
+ static internalError(message, cause) {
145
+ return this.create({
146
+ message,
147
+ code: 500,
148
+ category: "infrastructure" /* INFRASTRUCTURE */,
149
+ severity: "CRITICAL" /* CRITICAL */,
150
+ httpStatus: 500 /* INTERNAL_SERVER_ERROR */,
151
+ cause
152
+ });
153
+ }
154
+ }
155
+ class SilgiError extends Error {
156
+ code;
157
+ category;
158
+ severity;
159
+ httpStatus;
160
+ metadata;
161
+ context;
162
+ cause;
163
+ constructor(error) {
164
+ super(error.message);
165
+ this.name = "SilgiError";
166
+ this.code = error.code;
167
+ this.category = error.category;
168
+ this.severity = error.severity;
169
+ this.httpStatus = error.httpStatus;
170
+ this.metadata = error.metadata ?? { timestamp: Date.now() };
171
+ this.context = error.context;
172
+ this.cause = error.cause;
173
+ if (Error.captureStackTrace) {
174
+ Error.captureStackTrace(this, this.constructor);
175
+ }
176
+ }
177
+ toString() {
178
+ let str = `${this.name} [${this.code}] ${this.severity}: ${this.message}`;
179
+ str += `
180
+ Category: ${this.category}`;
181
+ str += `
182
+ HTTP Status: ${this.httpStatus}`;
183
+ if (this.context) {
184
+ str += `
185
+ Context: ${JSON.stringify(this.context, null, 2)}`;
186
+ }
187
+ if (this.metadata) {
188
+ str += `
189
+ Metadata: ${JSON.stringify(this.metadata, null, 2)}`;
190
+ }
191
+ if (this.stack) {
192
+ str += `
193
+ ${this.stack}`;
194
+ }
195
+ return str;
196
+ }
197
+ toJSON() {
198
+ return {
199
+ name: this.name,
200
+ code: this.code,
201
+ message: this.message,
202
+ category: this.category,
203
+ severity: this.severity,
204
+ httpStatus: this.httpStatus,
205
+ metadata: this.metadata,
206
+ context: this.context,
207
+ stack: this.stack
208
+ };
209
+ }
210
+ static isError(error) {
211
+ return error instanceof SilgiError || typeof error === "object" && error !== null && "name" in error && error.name === "SilgiError";
212
+ }
213
+ static from(error) {
214
+ if (error instanceof SilgiError) {
215
+ return error;
216
+ }
217
+ return ErrorFactory.internalError(
218
+ error instanceof Error ? error.message : String(error),
219
+ error instanceof Error ? error : void 0
220
+ );
221
+ }
222
+ }
223
+ function isBaseError(error) {
224
+ return typeof error === "object" && error !== null && "code" in error && "message" in error && "category" in error && "severity" in error && "httpStatus" in error;
225
+ }
226
+
227
+ export { ErrorCategory, ErrorFactory, ErrorSeverity, HttpStatus, SilgiError, isBaseError };
@@ -0,0 +1,8 @@
1
+ const autoImportTypes = [
2
+ "ExtractInputFromURI",
3
+ "ExtractOutputFromURI",
4
+ "ExtractPathParamsFromURI",
5
+ "ExtractQueryParamsFromURI"
6
+ ];
7
+
8
+ export { autoImportTypes };
@@ -0,0 +1,288 @@
1
+ import { withoutTrailingSlash, withLeadingSlash } from 'ufo';
2
+
3
+ function patternToRegex(pattern) {
4
+ let regexStr = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
5
+ regexStr = regexStr.replace(/\*\*/g, ".+");
6
+ regexStr = regexStr.replace(/\*/g, "[^/]+");
7
+ regexStr = regexStr.replace(/:([^/]+)/g, "([^/]+)");
8
+ return new RegExp(`^${regexStr}$`);
9
+ }
10
+ function extractParams(url, pattern) {
11
+ url = withoutTrailingSlash(withLeadingSlash(url));
12
+ pattern = withoutTrailingSlash(withLeadingSlash(pattern));
13
+ if (!pattern.includes(":"))
14
+ return null;
15
+ const paramNames = [];
16
+ const patternRegex = pattern.replace(/:([^/]+)/g, (_, name) => {
17
+ paramNames.push(name);
18
+ return "([^/]+)";
19
+ });
20
+ const regex = new RegExp(`^${patternRegex}$`);
21
+ const matches = url.match(regex);
22
+ if (!matches)
23
+ return null;
24
+ const params = {};
25
+ paramNames.forEach((name, i) => {
26
+ params[name] = matches[i + 1];
27
+ });
28
+ return Object.keys(params).length > 0 ? params : null;
29
+ }
30
+ function matchesPattern(url, pattern) {
31
+ url = withoutTrailingSlash(withLeadingSlash(url));
32
+ pattern = withoutTrailingSlash(withLeadingSlash(pattern));
33
+ if (url === pattern)
34
+ return true;
35
+ if (pattern.endsWith("/**")) {
36
+ const basePath = pattern.slice(0, -3);
37
+ return url === basePath || url.startsWith(`${basePath}/`);
38
+ }
39
+ const urlParts = url.split("/");
40
+ const patternParts = pattern.split("/");
41
+ if (!pattern.includes("**") && urlParts.length !== patternParts.length) {
42
+ return false;
43
+ }
44
+ if (pattern.includes("/**/")) {
45
+ const [prefix, ...suffixParts] = pattern.split("/**/");
46
+ const suffix = suffixParts.join("/");
47
+ return url.startsWith(prefix) && (!suffix || url.endsWith(`/${suffix}`));
48
+ }
49
+ return patternToRegex(pattern).test(url);
50
+ }
51
+ function deepClone(obj) {
52
+ if (obj === null || typeof obj !== "object")
53
+ return obj;
54
+ if (typeof obj === "function")
55
+ return obj;
56
+ if (Array.isArray(obj))
57
+ return obj.map(deepClone);
58
+ const cloned = {};
59
+ for (const key in obj) {
60
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
61
+ cloned[key] = deepClone(obj[key]);
62
+ }
63
+ }
64
+ return cloned;
65
+ }
66
+ function mergeConfigs(...configs) {
67
+ const result = {};
68
+ for (const config of configs) {
69
+ if (!config)
70
+ continue;
71
+ for (const key in config) {
72
+ const value = config[key];
73
+ if (value && typeof value === "object" && !Array.isArray(value) && result[key] && typeof result[key] === "object" && typeof result[key] !== "function") {
74
+ const resultValue = result[key];
75
+ const valueToMerge = value;
76
+ result[key] = mergeConfigs(resultValue, valueToMerge);
77
+ } else {
78
+ result[key] = value;
79
+ }
80
+ }
81
+ }
82
+ return result;
83
+ }
84
+ function createRouteRules() {
85
+ let _rules = {};
86
+ let _mergedRules = {};
87
+ let _rulesModified = false;
88
+ function getRules() {
89
+ return deepClone(_rules);
90
+ }
91
+ function importRules(config) {
92
+ const normalizedConfig = {};
93
+ for (const pattern in config) {
94
+ normalizedConfig[withoutTrailingSlash(withLeadingSlash(pattern))] = deepClone(config[pattern]);
95
+ }
96
+ _rules = normalizedConfig;
97
+ _rulesModified = true;
98
+ updateMergeRules();
99
+ }
100
+ function exportRules() {
101
+ return deepClone(_rules);
102
+ }
103
+ function addRule(pattern, config) {
104
+ _rules[withoutTrailingSlash(withLeadingSlash(pattern))] = deepClone(config);
105
+ _rulesModified = true;
106
+ updateMergeRules();
107
+ }
108
+ function updateRule(pattern, config) {
109
+ const normalizedPattern = withoutTrailingSlash(withLeadingSlash(pattern));
110
+ if (_rules[normalizedPattern]) {
111
+ _rules[normalizedPattern] = { ..._rules[normalizedPattern], ...deepClone(config) };
112
+ } else {
113
+ _rules[normalizedPattern] = deepClone(config);
114
+ }
115
+ _rulesModified = true;
116
+ updateMergeRules();
117
+ }
118
+ function removeRule(pattern) {
119
+ delete _rules[withoutTrailingSlash(withLeadingSlash(pattern))];
120
+ _rulesModified = true;
121
+ updateMergeRules();
122
+ }
123
+ function matchesRule(url, pattern) {
124
+ return matchesPattern(withoutTrailingSlash(withLeadingSlash(url)), withoutTrailingSlash(withLeadingSlash(pattern)));
125
+ }
126
+ function getMatchingPatterns(url) {
127
+ const normalizedUrl = withoutTrailingSlash(withLeadingSlash(url));
128
+ return Object.keys(_rules).filter((pattern) => matchesPattern(normalizedUrl, pattern)).sort((a, b) => {
129
+ if (a === url)
130
+ return -1;
131
+ if (b === url)
132
+ return 1;
133
+ const aSegments = a.split("/").filter(Boolean).length;
134
+ const bSegments = b.split("/").filter(Boolean).length;
135
+ if (aSegments !== bSegments)
136
+ return bSegments - aSegments;
137
+ const aWildcards = (a.match(/\*/g) || []).length;
138
+ const bWildcards = (b.match(/\*/g) || []).length;
139
+ if (aWildcards !== bWildcards)
140
+ return aWildcards - bWildcards;
141
+ const aDoubleWildcards = (a.match(/\*\*/g) || []).length;
142
+ const bDoubleWildcards = (b.match(/\*\*/g) || []).length;
143
+ if (aDoubleWildcards !== bDoubleWildcards)
144
+ return aDoubleWildcards - bDoubleWildcards;
145
+ return b.length - a.length;
146
+ });
147
+ }
148
+ function getConfig(url) {
149
+ const normalizedUrl = withoutTrailingSlash(withLeadingSlash(url));
150
+ if (_rulesModified) {
151
+ updateMergeRules();
152
+ }
153
+ if (_mergedRules[normalizedUrl]) {
154
+ return deepClone(_mergedRules[normalizedUrl]);
155
+ }
156
+ const patterns = getMatchingPatterns(normalizedUrl);
157
+ if (!patterns.length)
158
+ return null;
159
+ const mergedConfig = {};
160
+ for (let i = patterns.length - 1; i >= 0; i--) {
161
+ const pattern = patterns[i];
162
+ const patternConfig = _mergedRules[pattern] || _rules[pattern];
163
+ Object.assign(mergedConfig, deepClone(patternConfig));
164
+ }
165
+ _mergedRules[normalizedUrl] = deepClone(mergedConfig);
166
+ return mergedConfig;
167
+ }
168
+ function computeMergedConfig(url, patterns) {
169
+ const normalizedUrl = withoutTrailingSlash(withLeadingSlash(url));
170
+ const matchingPatterns = patterns || getMatchingPatterns(normalizedUrl);
171
+ if (!matchingPatterns.length)
172
+ return {};
173
+ const allPatternsHaveCache = matchingPatterns.every((pattern) => !!_mergedRules[pattern]);
174
+ if (allPatternsHaveCache) {
175
+ return matchingPatterns.reduceRight((result, pattern) => mergeConfigs(result, deepClone(_mergedRules[pattern])), {});
176
+ }
177
+ return matchingPatterns.reduceRight((result, pattern) => mergeConfigs(result, deepClone(_rules[pattern])), {});
178
+ }
179
+ function getParams(url, pattern) {
180
+ return extractParams(withoutTrailingSlash(withLeadingSlash(url)), withoutTrailingSlash(withLeadingSlash(pattern)));
181
+ }
182
+ function match(url) {
183
+ const normalizedUrl = withoutTrailingSlash(withLeadingSlash(url));
184
+ const patterns = getMatchingPatterns(normalizedUrl);
185
+ if (!patterns.length)
186
+ return null;
187
+ const bestPattern = patterns[0];
188
+ return {
189
+ pattern: bestPattern,
190
+ config: deepClone(_rules[bestPattern]),
191
+ params: getParams(normalizedUrl, bestPattern)
192
+ };
193
+ }
194
+ function clear() {
195
+ _rules = {};
196
+ clearMergedRules();
197
+ _rulesModified = false;
198
+ }
199
+ function clearMergedRules() {
200
+ _mergedRules = {};
201
+ _rulesModified = true;
202
+ }
203
+ function precomputeMergedRules(urls) {
204
+ if (_rulesModified) {
205
+ updateMergeRules();
206
+ }
207
+ for (const url of urls) {
208
+ const normalizedUrl = withoutTrailingSlash(withLeadingSlash(url));
209
+ if (!_mergedRules[normalizedUrl]) {
210
+ const patterns = getMatchingPatterns(normalizedUrl);
211
+ if (patterns.length) {
212
+ _mergedRules[normalizedUrl] = computeMergedConfig(normalizedUrl, patterns);
213
+ }
214
+ }
215
+ }
216
+ }
217
+ function setMergedRule(url, config) {
218
+ const normalizedUrl = withoutTrailingSlash(withLeadingSlash(url));
219
+ _mergedRules[normalizedUrl] = deepClone(config);
220
+ if (url.includes("*") || url.includes(":")) {
221
+ _rulesModified = false;
222
+ }
223
+ }
224
+ function getMergedRules() {
225
+ return deepClone(_mergedRules);
226
+ }
227
+ function configure(config) {
228
+ importRules(config);
229
+ }
230
+ function updateMergeRules() {
231
+ if (!_rulesModified) {
232
+ return _mergedRules;
233
+ }
234
+ _mergedRules = {};
235
+ const rulePatterns = Object.keys(_rules);
236
+ for (const pattern of rulePatterns) {
237
+ const patterns = getMatchingPatterns(pattern);
238
+ _mergedRules[pattern] = computeMergedConfig(pattern, patterns);
239
+ }
240
+ for (const pattern of rulePatterns) {
241
+ if (pattern.includes("/:")) {
242
+ const segments = pattern.split("/");
243
+ let partialPath = "";
244
+ for (const segment of segments) {
245
+ if (segment) {
246
+ partialPath += `/${segment}`;
247
+ if (segment.startsWith(":") && partialPath !== pattern) {
248
+ const samplePath = partialPath.replace(/:\w+/g, "sample");
249
+ const patterns = getMatchingPatterns(samplePath);
250
+ _mergedRules[samplePath] = computeMergedConfig(samplePath, patterns);
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
256
+ _rulesModified = false;
257
+ return _mergedRules;
258
+ }
259
+ return {
260
+ // Public getters that return a cloned version to prevent direct modification
261
+ get rules() {
262
+ return getRules();
263
+ },
264
+ get mergedRules() {
265
+ return getMergedRules();
266
+ },
267
+ // API methods
268
+ importRules,
269
+ exportRules,
270
+ addRule,
271
+ updateRule,
272
+ removeRule,
273
+ matchesRule,
274
+ getMatchingPatterns,
275
+ getConfig,
276
+ getParams,
277
+ match,
278
+ clear,
279
+ clearMergedRules,
280
+ precomputeMergedRules,
281
+ setMergedRule,
282
+ getMergedRules,
283
+ configure,
284
+ updateMergeRules
285
+ };
286
+ }
287
+
288
+ export { createRouteRules };
@@ -0,0 +1,128 @@
1
+ import { defu } from 'defu';
2
+ import { ErrorFactory, HttpStatus, SilgiError } from './error.mjs';
3
+ import { useSilgi, normalizeResult } from './unctx.mjs';
4
+ import { parseURI } from './uris/utils.mjs';
5
+ import { useSilgiStorage, generateStorageKey } from './utils/storage.mjs';
6
+
7
+ function silgi(event) {
8
+ return {
9
+ execute: (uriString, input, source, queryParams) => {
10
+ return execute(uriString, input, event, source, queryParams);
11
+ }
12
+ };
13
+ }
14
+ async function execute(uriString, input, event, source, queryParams) {
15
+ const silgiCtx = useSilgi();
16
+ const config = {
17
+ returnNull: false
18
+ };
19
+ try {
20
+ const operation = parseURI(uriString, silgiCtx.uris);
21
+ if (!operation) {
22
+ throw ErrorFactory.create({ message: "Invalid URI", httpStatus: HttpStatus.BAD_REQUEST });
23
+ }
24
+ let success = false;
25
+ let cached = false;
26
+ let result;
27
+ const handler = silgiCtx.scannedHandlers.get(operation.uri);
28
+ if (!handler) {
29
+ throw ErrorFactory.create({
30
+ message: "execute not found",
31
+ httpStatus: HttpStatus.NOT_FOUND,
32
+ context: {
33
+ uri: uriString
34
+ }
35
+ });
36
+ }
37
+ await silgiCtx.callHook("execute:before", {
38
+ operation,
39
+ input,
40
+ event,
41
+ modules: handler.modules,
42
+ source,
43
+ config
44
+ });
45
+ if (config.returnNull) {
46
+ return result;
47
+ }
48
+ const cacheData = await cacheExecute(input, operation, handler, event);
49
+ if (cacheData?.success) {
50
+ result = cacheData.data;
51
+ success = cacheData.success;
52
+ cached = cacheData.cached;
53
+ } else {
54
+ let parameters = defu(operation.routerParams, operation.query) || {};
55
+ if (queryParams) {
56
+ parameters = defu(queryParams, parameters);
57
+ }
58
+ silgiCtx.shared.silgi = silgi(event);
59
+ result = await handler?.handler(
60
+ defu(input, { parameters }),
61
+ silgiCtx.shared,
62
+ event,
63
+ source
64
+ );
65
+ success = true;
66
+ }
67
+ await silgiCtx.callHook("execute:after", {
68
+ operation,
69
+ input,
70
+ event,
71
+ result,
72
+ success,
73
+ source,
74
+ modules: handler.modules,
75
+ config
76
+ });
77
+ if (!cached) {
78
+ if (success && cacheData?.cachedKey && handler.storage) {
79
+ await useSilgiStorage(handler.storage.base).setItem(cacheData.cachedKey, result, handler.storage.options);
80
+ }
81
+ }
82
+ return result;
83
+ } catch (err) {
84
+ await silgiCtx.callHook("execute:error", {
85
+ input,
86
+ event,
87
+ source,
88
+ error: err instanceof Error ? err : new Error(String(err)),
89
+ timestamp: Date.now(),
90
+ config
91
+ });
92
+ silgiCtx.captureError(SilgiError.from(err), {
93
+ event,
94
+ tags: ["execute"]
95
+ });
96
+ throw err;
97
+ }
98
+ }
99
+ async function cacheExecute(input, operation, handler, event) {
100
+ if (!handler.storage)
101
+ return;
102
+ const cacheKey = handler.storage ? await generateStorageKey({
103
+ operation,
104
+ input,
105
+ keyGenerator: handler.storage.key,
106
+ storageOptions: handler.storage,
107
+ requestId: event?.requestId
108
+ }) : null;
109
+ if (cacheKey) {
110
+ const cachedResult = await useSilgiStorage(handler.storage.base).getItem(cacheKey);
111
+ if (cachedResult !== null) {
112
+ return {
113
+ success: true,
114
+ data: normalizeResult(cachedResult),
115
+ cached: true,
116
+ cachedKey: cacheKey
117
+ };
118
+ }
119
+ }
120
+ return {
121
+ success: false,
122
+ data: null,
123
+ cached: false,
124
+ cachedKey: cacheKey
125
+ };
126
+ }
127
+
128
+ export { execute, silgi };
@@ -0,0 +1,25 @@
1
+ import consola from 'consola';
2
+ import { createContext } from 'unctx';
3
+
4
+ const silgiCLICtx = createContext();
5
+ function useSilgiCLI() {
6
+ const instance = silgiCLICtx.tryUse();
7
+ if (!instance) {
8
+ throw new Error("Silgi instance is unavailable!");
9
+ }
10
+ return instance;
11
+ }
12
+ async function silgiCLIIClose() {
13
+ const silgi = silgiCLICtx.tryUse();
14
+ if (!silgi) {
15
+ return;
16
+ }
17
+ await silgi.close();
18
+ await silgi.callHook("close", silgi);
19
+ consola.withTag("silgi").success("Process terminated");
20
+ }
21
+ function tryUseSilgiCLI() {
22
+ return silgiCLICtx.tryUse();
23
+ }
24
+
25
+ export { silgiCLICtx, silgiCLIIClose, tryUseSilgiCLI, useSilgiCLI };
@@ -0,0 +1,15 @@
1
+ import { useSilgi } from './unctx.mjs';
2
+
3
+ function storageMount(silgi) {
4
+ const _silgi = silgi || useSilgi();
5
+ return (base, driver) => {
6
+ const existingStorage = _silgi.storage.getMount(base);
7
+ if (existingStorage) {
8
+ return existingStorage.driver;
9
+ }
10
+ const storage = _silgi.storage.mount(base, driver);
11
+ return storage;
12
+ };
13
+ }
14
+
15
+ export { storageMount };