silgi 0.0.13 → 0.1.0-beta.1

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 (186) hide show
  1. package/README.md +102 -1
  2. package/dist/_virtual/_rolldown/runtime.mjs +5 -0
  3. package/dist/adapters/astro.d.mts +17 -0
  4. package/dist/adapters/astro.mjs +24 -0
  5. package/dist/adapters/aws-lambda.d.mts +31 -0
  6. package/dist/adapters/aws-lambda.mjs +85 -0
  7. package/dist/adapters/elysia.d.mts +17 -0
  8. package/dist/adapters/elysia.mjs +76 -0
  9. package/dist/adapters/express.d.mts +16 -0
  10. package/dist/adapters/express.mjs +78 -0
  11. package/dist/adapters/fastify.d.mts +15 -0
  12. package/dist/adapters/fastify.mjs +78 -0
  13. package/dist/adapters/message-port.d.mts +37 -0
  14. package/dist/adapters/message-port.mjs +129 -0
  15. package/dist/adapters/nestjs.d.mts +25 -0
  16. package/dist/adapters/nestjs.mjs +91 -0
  17. package/dist/adapters/nextjs.d.mts +21 -0
  18. package/dist/adapters/nextjs.mjs +30 -0
  19. package/dist/adapters/peer.d.mts +27 -0
  20. package/dist/adapters/peer.mjs +36 -0
  21. package/dist/adapters/remix.d.mts +17 -0
  22. package/dist/adapters/remix.mjs +24 -0
  23. package/dist/adapters/solidstart.d.mts +14 -0
  24. package/dist/adapters/solidstart.mjs +30 -0
  25. package/dist/adapters/sveltekit.d.mts +18 -0
  26. package/dist/adapters/sveltekit.mjs +33 -0
  27. package/dist/analyze.mjs +26 -0
  28. package/dist/broker/index.d.mts +62 -0
  29. package/dist/broker/index.mjs +153 -0
  30. package/dist/broker/nats.d.mts +33 -0
  31. package/dist/broker/nats.mjs +31 -0
  32. package/dist/broker/redis.d.mts +51 -0
  33. package/dist/broker/redis.mjs +92 -0
  34. package/dist/builder.d.mts +36 -0
  35. package/dist/builder.mjs +51 -0
  36. package/dist/callable.d.mts +17 -0
  37. package/dist/callable.mjs +42 -0
  38. package/dist/client/adapters/fetch/index.d.mts +17 -0
  39. package/dist/client/adapters/fetch/index.mjs +61 -0
  40. package/dist/client/adapters/ofetch/index.d.mts +41 -0
  41. package/dist/client/adapters/ofetch/index.mjs +92 -0
  42. package/dist/client/client.d.mts +29 -0
  43. package/dist/client/client.mjs +54 -0
  44. package/dist/client/dynamic-link.d.mts +15 -0
  45. package/dist/client/dynamic-link.mjs +16 -0
  46. package/dist/client/index.d.mts +7 -0
  47. package/dist/client/index.mjs +6 -0
  48. package/dist/client/interceptor.d.mts +31 -0
  49. package/dist/client/interceptor.mjs +34 -0
  50. package/dist/client/merge.d.mts +28 -0
  51. package/dist/client/merge.mjs +30 -0
  52. package/dist/client/openapi.d.mts +29 -0
  53. package/dist/client/openapi.mjs +89 -0
  54. package/dist/client/plugins/batch.d.mts +20 -0
  55. package/dist/client/plugins/batch.mjs +64 -0
  56. package/dist/client/plugins/csrf.d.mts +13 -0
  57. package/dist/client/plugins/csrf.mjs +20 -0
  58. package/dist/client/plugins/dedupe.d.mts +10 -0
  59. package/dist/client/plugins/dedupe.mjs +28 -0
  60. package/dist/client/plugins/index.d.mts +5 -0
  61. package/dist/client/plugins/index.mjs +5 -0
  62. package/dist/client/plugins/retry.d.mts +11 -0
  63. package/dist/client/plugins/retry.mjs +21 -0
  64. package/dist/client/server.d.mts +16 -0
  65. package/dist/client/server.mjs +60 -0
  66. package/dist/client/types.d.mts +29 -0
  67. package/dist/codec/devalue.d.mts +21 -0
  68. package/dist/codec/devalue.mjs +32 -0
  69. package/dist/codec/msgpack.d.mts +21 -0
  70. package/dist/codec/msgpack.mjs +59 -0
  71. package/dist/compile.d.mts +52 -0
  72. package/dist/compile.mjs +304 -0
  73. package/dist/contract.d.mts +36 -0
  74. package/dist/contract.mjs +40 -0
  75. package/dist/core/error.d.mts +104 -0
  76. package/dist/core/error.mjs +139 -0
  77. package/dist/core/handler.mjs +546 -0
  78. package/dist/core/iterator.d.mts +17 -0
  79. package/dist/core/iterator.mjs +79 -0
  80. package/dist/core/router-utils.mjs +16 -0
  81. package/dist/core/schema.d.mts +19 -0
  82. package/dist/core/schema.mjs +26 -0
  83. package/dist/core/serve.mjs +38 -0
  84. package/dist/core/sse.d.mts +16 -0
  85. package/dist/core/sse.mjs +95 -0
  86. package/dist/core/storage.d.mts +21 -0
  87. package/dist/core/storage.mjs +63 -0
  88. package/dist/core/utils.mjs +21 -0
  89. package/dist/fast-stringify.mjs +125 -0
  90. package/dist/index.d.mts +15 -37
  91. package/dist/index.mjs +13 -7
  92. package/dist/integrations/ai/index.d.mts +25 -0
  93. package/dist/integrations/ai/index.mjs +116 -0
  94. package/dist/integrations/react/index.d.mts +83 -0
  95. package/dist/integrations/react/index.mjs +197 -0
  96. package/dist/integrations/tanstack-query/index.d.mts +120 -0
  97. package/dist/integrations/tanstack-query/index.mjs +100 -0
  98. package/dist/integrations/tanstack-query/ssr.d.mts +51 -0
  99. package/dist/integrations/tanstack-query/ssr.mjs +89 -0
  100. package/dist/integrations/zod/converter.d.mts +75 -0
  101. package/dist/integrations/zod/converter.mjs +345 -0
  102. package/dist/integrations/zod/index.d.mts +2 -0
  103. package/dist/integrations/zod/index.mjs +2 -0
  104. package/dist/lazy.d.mts +24 -0
  105. package/dist/lazy.mjs +27 -0
  106. package/dist/lifecycle.d.mts +36 -0
  107. package/dist/lifecycle.mjs +46 -0
  108. package/dist/map-input.d.mts +17 -0
  109. package/dist/map-input.mjs +24 -0
  110. package/dist/plugins/analytics.d.mts +168 -0
  111. package/dist/plugins/analytics.mjs +459 -0
  112. package/dist/plugins/batch-server.d.mts +20 -0
  113. package/dist/plugins/batch-server.mjs +86 -0
  114. package/dist/plugins/body-limit.d.mts +16 -0
  115. package/dist/plugins/body-limit.mjs +44 -0
  116. package/dist/plugins/cache.d.mts +170 -0
  117. package/dist/plugins/cache.mjs +200 -0
  118. package/dist/plugins/coerce.d.mts +21 -0
  119. package/dist/plugins/coerce.mjs +46 -0
  120. package/dist/plugins/compression.d.mts +19 -0
  121. package/dist/plugins/compression.mjs +23 -0
  122. package/dist/plugins/cookies.d.mts +44 -0
  123. package/dist/plugins/cookies.mjs +67 -0
  124. package/dist/plugins/cors.d.mts +39 -0
  125. package/dist/plugins/cors.mjs +56 -0
  126. package/dist/plugins/custom-serializer.d.mts +57 -0
  127. package/dist/plugins/custom-serializer.mjs +40 -0
  128. package/dist/plugins/file-upload.d.mts +38 -0
  129. package/dist/plugins/file-upload.mjs +100 -0
  130. package/dist/plugins/index.d.mts +16 -0
  131. package/dist/plugins/index.mjs +16 -0
  132. package/dist/plugins/otel.d.mts +35 -0
  133. package/dist/plugins/otel.mjs +40 -0
  134. package/dist/plugins/pino.d.mts +60 -0
  135. package/dist/plugins/pino.mjs +42 -0
  136. package/dist/plugins/pubsub.d.mts +50 -0
  137. package/dist/plugins/pubsub.mjs +53 -0
  138. package/dist/plugins/ratelimit.d.mts +51 -0
  139. package/dist/plugins/ratelimit.mjs +81 -0
  140. package/dist/plugins/signing.d.mts +41 -0
  141. package/dist/plugins/signing.mjs +115 -0
  142. package/dist/plugins/strict-get.d.mts +10 -0
  143. package/dist/plugins/strict-get.mjs +33 -0
  144. package/dist/route/add.mjs +240 -0
  145. package/dist/route/compiler.mjs +373 -0
  146. package/dist/route/context.mjs +12 -0
  147. package/dist/route/types.d.mts +11 -0
  148. package/dist/route/utils.mjs +17 -0
  149. package/dist/scalar.d.mts +53 -0
  150. package/dist/scalar.mjs +315 -0
  151. package/dist/silgi.d.mts +139 -0
  152. package/dist/silgi.mjs +113 -0
  153. package/dist/trpc-interop.d.mts +22 -0
  154. package/dist/trpc-interop.mjs +68 -0
  155. package/dist/types.d.mts +82 -0
  156. package/dist/ws.d.mts +42 -0
  157. package/dist/ws.mjs +137 -0
  158. package/lib/dashboard/index.html +123 -0
  159. package/lib/ocache.d.mts +1 -0
  160. package/lib/ocache.mjs +1 -0
  161. package/lib/ofetch.d.mts +1 -0
  162. package/lib/ofetch.mjs +1 -0
  163. package/lib/srvx.d.mts +1 -0
  164. package/lib/srvx.mjs +1 -0
  165. package/lib/unstorage.d.mts +1 -0
  166. package/lib/unstorage.mjs +1 -0
  167. package/package.json +291 -65
  168. package/bin/silgi.mjs +0 -3
  169. package/dist/chunks/generate.mjs +0 -933
  170. package/dist/chunks/init.mjs +0 -21
  171. package/dist/cli/config.d.mts +0 -19
  172. package/dist/cli/config.d.ts +0 -19
  173. package/dist/cli/config.mjs +0 -5
  174. package/dist/cli/index.d.mts +0 -2
  175. package/dist/cli/index.d.ts +0 -2
  176. package/dist/cli/index.mjs +0 -119
  177. package/dist/index.d.ts +0 -37
  178. package/dist/plugins/openapi.d.mts +0 -138
  179. package/dist/plugins/openapi.d.ts +0 -138
  180. package/dist/plugins/openapi.mjs +0 -204
  181. package/dist/plugins/scalar.d.mts +0 -14
  182. package/dist/plugins/scalar.d.ts +0 -14
  183. package/dist/plugins/scalar.mjs +0 -66
  184. package/dist/shared/silgi.BMCYk2cR.mjs +0 -841
  185. package/dist/shared/silgi.D5qK9QOm.d.mts +0 -301
  186. package/dist/shared/silgi.D5qK9QOm.d.ts +0 -301
@@ -1,841 +0,0 @@
1
- import consola, { createConsola } from 'consola';
2
- import { createHooks } from 'hookable';
3
- import { Buffer } from 'node:buffer';
4
- import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync } from 'node:fs';
5
- import { join } from 'node:path';
6
- import { getContext } from 'unctx';
7
-
8
- class PergelError extends Error {
9
- code;
10
- details;
11
- meta;
12
- timestamp;
13
- constructor(options) {
14
- super(options.message);
15
- this.name = "PergelError";
16
- this.code = options.code;
17
- this.details = options.details;
18
- this.meta = options.meta;
19
- this.timestamp = Date.now();
20
- if (Error.captureStackTrace) {
21
- Error.captureStackTrace(this, this.constructor);
22
- }
23
- }
24
- // Improve error formatting
25
- toString() {
26
- let errorString = `[${this.code}] ${this.message}`;
27
- if (this.details) {
28
- errorString += `
29
- Details: ${JSON.stringify(this.details, null, 2)}`;
30
- }
31
- return errorString;
32
- }
33
- toJSON() {
34
- return {
35
- name: this.name,
36
- code: this.code,
37
- message: this.message,
38
- details: this.details,
39
- meta: this.meta,
40
- timestamp: this.timestamp,
41
- stack: this.stack
42
- };
43
- }
44
- static createFrom(error, code = "UNKNOWN_ERROR") {
45
- if (error instanceof PergelError) {
46
- return error;
47
- }
48
- return new PergelError({
49
- code,
50
- message: error instanceof Error ? error.message : String(error),
51
- cause: error instanceof Error ? error : undefined
52
- });
53
- }
54
- static isPergelError(error) {
55
- return error instanceof PergelError;
56
- }
57
- }
58
-
59
- class MemoryCacheProvider {
60
- cache = /* @__PURE__ */ new Map();
61
- constructor(options = {}) {
62
- if (options.maxSize) {
63
- setInterval(() => {
64
- if (this.cache.size > options.maxSize) {
65
- const entries = Array.from(this.cache.entries());
66
- entries.sort(([, a], [, b]) => a.expiry - b.expiry);
67
- const toDelete = entries.slice(0, entries.length - options.maxSize);
68
- toDelete.forEach(([key]) => this.cache.delete(key));
69
- }
70
- }, 1e3);
71
- }
72
- }
73
- async get(key) {
74
- const entry = this.cache.get(key);
75
- if (!entry)
76
- return null;
77
- if (Date.now() > entry.expiry) {
78
- this.cache.delete(key);
79
- return null;
80
- }
81
- return entry.value;
82
- }
83
- async set(key, value, ttl) {
84
- this.cache.set(key, {
85
- value,
86
- expiry: Date.now() + ttl
87
- });
88
- }
89
- async delete(key) {
90
- this.cache.delete(key);
91
- }
92
- async clear() {
93
- this.cache.clear();
94
- }
95
- }
96
- class FileCacheProvider {
97
- constructor(options = {}) {
98
- this.options = options;
99
- this.cacheDir = options.dir || join(process.cwd(), ".cache", "pergel");
100
- if (!existsSync(this.cacheDir))
101
- mkdirSync(this.cacheDir, { recursive: true });
102
- }
103
- cacheDir;
104
- getFilePath(key) {
105
- const safeKey = Buffer.from(key).toString("base64");
106
- return join(this.cacheDir, `${safeKey}.json`);
107
- }
108
- async get(key) {
109
- try {
110
- const filePath = this.getFilePath(key);
111
- if (!existsSync(filePath))
112
- return null;
113
- const data = JSON.parse(readFileSync(filePath, "utf-8"));
114
- if (Date.now() > data.expiry) {
115
- await this.delete(key);
116
- return null;
117
- }
118
- return data.value;
119
- } catch {
120
- return null;
121
- }
122
- }
123
- async set(key, value, ttl) {
124
- const filePath = this.getFilePath(key);
125
- const data = {
126
- value,
127
- expiry: Date.now() + ttl
128
- };
129
- writeFileSync(filePath, JSON.stringify(data), "utf-8");
130
- }
131
- async delete(key) {
132
- try {
133
- unlinkSync(this.getFilePath(key));
134
- } catch {
135
- }
136
- }
137
- async clear() {
138
- try {
139
- const files = existsSync(this.cacheDir) ? readdirSync(this.cacheDir) : [];
140
- for (const file of files)
141
- unlinkSync(join(this.cacheDir, file));
142
- } catch {
143
- }
144
- }
145
- }
146
-
147
- const logger$1 = consola.withTag("pergel");
148
- class PluginManager {
149
- // Removed readonly
150
- constructor(silgi) {
151
- this.silgi = silgi;
152
- }
153
- plugins = /* @__PURE__ */ new Map();
154
- pluginPriorities = /* @__PURE__ */ new Map();
155
- log(message, ...args) {
156
- if (this.silgi.silgi.options.debug)
157
- logger$1.withTag("plugin").log(message, ...args);
158
- }
159
- register(plugin) {
160
- const pluginName = String(plugin.name);
161
- this.log(`Registering plugin: ${pluginName}`);
162
- if (this.plugins.has(pluginName)) {
163
- throw new PergelError({
164
- code: "PLUGIN_ALREADY_EXISTS",
165
- message: `Plugin ${pluginName} already registered`
166
- });
167
- }
168
- this.plugins.set(pluginName, plugin);
169
- this.calculatePluginPriorities();
170
- }
171
- calculatePluginPriorities() {
172
- const visited = /* @__PURE__ */ new Set();
173
- const priorities = /* @__PURE__ */ new Map();
174
- const baseOffset = 1e3;
175
- const getBasePriority = (priority) => {
176
- switch (priority) {
177
- case "HIGHEST":
178
- return baseOffset * 5;
179
- case "HIGH":
180
- return baseOffset * 4;
181
- case "NORMAL":
182
- return baseOffset * 3;
183
- case "LOW":
184
- return baseOffset * 2;
185
- case "LOWEST":
186
- return baseOffset;
187
- default:
188
- return baseOffset * 3;
189
- }
190
- };
191
- const visit = (pluginName, depth = 0) => {
192
- if (visited.has(pluginName))
193
- return priorities.get(pluginName) || 0;
194
- visited.add(pluginName);
195
- const plugin = this.plugins.get(pluginName);
196
- if (!plugin)
197
- return 0;
198
- let priority = getBasePriority(plugin.priority || "NORMAL");
199
- const deps = plugin.dependencies || [];
200
- for (const dep of deps) {
201
- const depName = String(dep);
202
- const depPriority = visit(depName, depth + 1);
203
- priority = Math.min(priority, depPriority - baseOffset / (depth + 1));
204
- }
205
- priorities.set(pluginName, priority);
206
- return priority;
207
- };
208
- for (const pluginName of this.plugins.keys()) {
209
- visit(pluginName);
210
- }
211
- const validateDependencies = (pluginName, chain = /* @__PURE__ */ new Set()) => {
212
- const plugin = this.plugins.get(pluginName);
213
- if (!plugin)
214
- return;
215
- if (chain.has(pluginName)) {
216
- throw new PergelError({
217
- code: "CIRCULAR_DEPENDENCY",
218
- message: `Circular dependency detected: ${Array.from(chain).join(" -> ")} -> ${pluginName}`
219
- });
220
- }
221
- chain.add(pluginName);
222
- for (const dep of plugin.dependencies || []) {
223
- validateDependencies(String(dep), new Set(chain));
224
- }
225
- };
226
- for (const pluginName of this.plugins.keys()) {
227
- validateDependencies(pluginName);
228
- }
229
- this.pluginPriorities = priorities;
230
- this.log("Plugin priorities:", Object.fromEntries([...priorities.entries()].sort((a, b) => b[1] - a[1]).map(([name, pri]) => [name, { priority: pri, basePriority: this.plugins.get(name)?.priority || "NORMAL" }])));
231
- }
232
- async runSetupHook() {
233
- const sortedPlugins = [...this.plugins.values()].sort((a, b) => {
234
- const priorityA = this.pluginPriorities.get(String(a.name)) ?? 0;
235
- const priorityB = this.pluginPriorities.get(String(b.name)) ?? 0;
236
- return priorityB - priorityA;
237
- });
238
- for (const plugin of sortedPlugins) {
239
- if (plugin.dependencies?.length) {
240
- for (const dep of plugin.dependencies) {
241
- const depPlugin = this.plugins.get(String(dep));
242
- if (!depPlugin) {
243
- throw new PergelError({
244
- code: "PLUGIN_DEPENDENCY_MISSING",
245
- message: `Plugin ${String(plugin.name)} depends on ${String(dep)} which is not registered`
246
- });
247
- }
248
- }
249
- }
250
- try {
251
- await plugin.setup?.(plugin.defaults || {}, this.silgi);
252
- consola.success(`Plugin ${String(plugin.name)} setup completed`);
253
- await this.silgi.silgi.callHook("plugin:setup:finish", {
254
- plugin,
255
- initSilgi: this.silgi
256
- });
257
- } catch (error) {
258
- this.plugins.delete(String(plugin.name));
259
- throw new PergelError({
260
- code: "PLUGIN_SETUP_ERROR",
261
- message: `Failed to setup plugin ${String(plugin.name)}`,
262
- cause: error instanceof Error ? error : undefined
263
- });
264
- }
265
- }
266
- }
267
- async runHook(hookName, context) {
268
- const ctx = {
269
- ...context
270
- };
271
- this.log(`Running hook: ${String(hookName)}`, {
272
- scope: context?.scope ? String(context.scope) : undefined,
273
- serviceName: context?.serviceName ? String(context.serviceName) : undefined,
274
- methodName: context?.methodName
275
- });
276
- const sortedPlugins = [...this.plugins.values()].sort((a, b) => {
277
- const priorityA = this.pluginPriorities.get(String(a.name)) ?? 0;
278
- const priorityB = this.pluginPriorities.get(String(b.name)) ?? 0;
279
- return priorityB - priorityA;
280
- });
281
- for (const plugin of sortedPlugins) {
282
- await this.executePluginHook(plugin, hookName, ctx);
283
- }
284
- }
285
- async executePluginHook(plugin, hookName, context) {
286
- const pluginName = String(plugin.name);
287
- try {
288
- const hookIndex = this.silgi.silgi.hooksNames.indexOf(hookName);
289
- if (hookIndex === -1)
290
- return;
291
- const service = context.serviceName && context.scope ? this.silgi.getService(context.scope, context.serviceName) : void 0;
292
- if (!service)
293
- return;
294
- const methodName = context.methodName;
295
- const methodPluginConfig = methodName ? service.methodPlugins?.[methodName]?.[pluginName] : void 0;
296
- const servicePluginConfig = service.plugins?.[pluginName];
297
- const shouldExecute = (() => {
298
- if (methodPluginConfig?.active !== void 0)
299
- return methodPluginConfig.active;
300
- if (servicePluginConfig?.active !== void 0)
301
- return servicePluginConfig.active;
302
- return false;
303
- })();
304
- if (shouldExecute) {
305
- const config = methodPluginConfig || servicePluginConfig || {};
306
- try {
307
- await this.silgi.silgi.callHook(hookName, {
308
- ...context,
309
- meta: config
310
- });
311
- } catch (error) {
312
- throw new PergelError({
313
- code: "PLUGIN_BLOCKED",
314
- message: `Plugin ${pluginName} blocked execution of ${hookName} hook${error instanceof Error ? `: ${error.message}` : ""}`,
315
- details: {
316
- pluginName,
317
- hookName,
318
- methodName,
319
- config
320
- }
321
- });
322
- }
323
- }
324
- } catch (error) {
325
- const errorContext = {
326
- plugin: pluginName,
327
- hook: hookName,
328
- scope: context.scope ? String(context.scope) : undefined,
329
- service: context.serviceName ? String(context.serviceName) : undefined,
330
- method: context.methodName
331
- };
332
- this.log(`Plugin error in ${pluginName}.${String(hookName)}:`, {
333
- ...errorContext,
334
- error: error instanceof Error ? error.message : String(error)
335
- });
336
- await this.handlePluginError(plugin, String(hookName), error, context);
337
- throw error;
338
- }
339
- }
340
- // New method for plugin error handling
341
- async handlePluginError(plugin, hookName, error, context) {
342
- try {
343
- this.silgi.silgi.callHook("app:error", {
344
- ...context,
345
- error: error instanceof Error ? error : new Error(String(error)),
346
- hookName
347
- });
348
- } catch (errorHandlingError) {
349
- this.log(`Failed to handle error in plugin ${String(plugin.name)}`, errorHandlingError);
350
- }
351
- }
352
- // Plugin'i ismine göre getir
353
- async getPlugin(name) {
354
- return this.plugins.get(name);
355
- }
356
- isPluginsRegistered() {
357
- return this.plugins.size > 0;
358
- }
359
- }
360
-
361
- const silgiCtx = getContext("silgi");
362
- function useShared() {
363
- const instance = silgiCtx.tryUse();
364
- if (!instance) {
365
- throw new Error("Nuxt instance is unavailable!");
366
- }
367
- return instance.silgi.options.shared;
368
- }
369
- function useSilgi() {
370
- const instance = silgiCtx.tryUse();
371
- if (!instance) {
372
- throw new Error("Nuxt instance is unavailable!");
373
- }
374
- return instance;
375
- }
376
- function useHook() {
377
- const instance = silgiCtx.tryUse();
378
- if (!instance) {
379
- throw new Error("Nuxt instance is unavailable!");
380
- }
381
- return instance.silgi.hooks.hook;
382
- }
383
-
384
- const logger = consola.withTag("pergel");
385
- class InitSilgi {
386
- silgi;
387
- constructor(silgi) {
388
- this.silgi = silgi;
389
- this.silgi.options._cacheProvider = this.createCacheProvider(this.silgi.options.cache, this.silgi.options.shared);
390
- this.silgi.options._pluginManager = new PluginManager(this);
391
- this.silgi.options.shared = this.silgi.options.shared ?? {};
392
- this.silgi.options._serviceRegistry = /* @__PURE__ */ new Map();
393
- this.silgi.options.services.forEach((service) => {
394
- const key = `${service.scope}:${service.name}`;
395
- this.silgi.options._serviceRegistry.set(key, service);
396
- });
397
- if (silgiCtx.tryUse()) {
398
- silgiCtx.unset();
399
- silgiCtx.set(this);
400
- logger.success("Silgi context replaced");
401
- } else {
402
- silgiCtx.set(this);
403
- silgi.hook("close", () => silgiCtx.unset());
404
- }
405
- consola.info("Silgi initialized");
406
- }
407
- // Helper to create cache provider
408
- createCacheProvider(cacheOptions, context) {
409
- const options = cacheOptions ?? { type: "memory" };
410
- if (options.provider) {
411
- return typeof options.provider === "function" ? options.provider(context) : options.provider;
412
- }
413
- switch (options.type ?? "memory") {
414
- case "file":
415
- return new FileCacheProvider(options.options?.file);
416
- case "memory":
417
- default:
418
- return new MemoryCacheProvider(options.options?.memory);
419
- }
420
- }
421
- log(message, ...args) {
422
- if (this.silgi.options.debug)
423
- logger.log(message, ...args);
424
- }
425
- async use(plugin) {
426
- const start = (/* @__PURE__ */ new Date()).getTime();
427
- this.log("Registering plugins");
428
- this.silgi.callHook("plugin:register:before", plugin);
429
- const plugins = Array.isArray(plugin) ? plugin : [plugin];
430
- await Promise.all(plugins.map((p) => this.silgi.options._pluginManager.register(p)));
431
- await this.silgi.options._pluginManager.runSetupHook();
432
- this.silgi.callHook("plugin:register:after", plugin);
433
- this.log("Plugins registered successfully");
434
- const finish = (/* @__PURE__ */ new Date()).getTime();
435
- consola.withTag("silgi").info(`Plugins registered ${finish - start}ms`);
436
- }
437
- getService(scope, name) {
438
- const key = `${String(scope)}:${String(name)}`;
439
- const service = this.silgi.options._serviceRegistry.get(key);
440
- if (!service) {
441
- throw new PergelError({
442
- code: "SERVICE_NOT_FOUND",
443
- message: `Service ${String(name)} not found in scope ${String(scope)}`
444
- });
445
- }
446
- return service;
447
- }
448
- listScopes() {
449
- const scopes = /* @__PURE__ */ new Set();
450
- for (const key of this.silgi.options._serviceRegistry.keys()) {
451
- const [scope] = key.split(":");
452
- scopes.add(scope);
453
- }
454
- return Array.from(scopes);
455
- }
456
- getScope(scope) {
457
- const services = [];
458
- for (const key of this.silgi.options._serviceRegistry.keys()) {
459
- if (key.startsWith(`${String(scope)}:`)) {
460
- const [, name] = key.split(":");
461
- services.push(name);
462
- }
463
- }
464
- return {
465
- name: services,
466
- scope: String(scope)
467
- };
468
- }
469
- // Bunun yerine daha açıklayıcı metodlar ekliyoruz:
470
- getScopeServices(scope) {
471
- const services = [];
472
- for (const [key, service] of this.silgi.options._serviceRegistry.entries()) {
473
- if (key.startsWith(`${String(scope)}:`)) {
474
- const [, name] = key.split(":");
475
- services.push([name, service]);
476
- }
477
- }
478
- return {
479
- services: services.map(([name]) => name),
480
- scope,
481
- methods: services.reduce((acc, [name, service]) => ({
482
- ...acc,
483
- [String(name)]: Array.from(service.handlers.keys())
484
- }), {})
485
- };
486
- }
487
- getAllServices() {
488
- const scopes = this.listScopes();
489
- return scopes.reduce((acc, scope) => ({
490
- ...acc,
491
- [scope]: this.getScopeServices(scope)
492
- }), {});
493
- }
494
- scope(scope, context) {
495
- return {
496
- service: (serviceName) => {
497
- const service = this.getService(scope, serviceName);
498
- return {
499
- execute: (methodName, input) => {
500
- return service.execute(methodName, input, {
501
- initSilgi: this,
502
- scope: String(scope),
503
- serviceName: String(serviceName),
504
- methodName: String(methodName),
505
- requestContext: context
506
- });
507
- }
508
- };
509
- }
510
- };
511
- }
512
- async getFromCache(key) {
513
- return this.silgi.options._cacheProvider.get(key);
514
- }
515
- async setInCache(key, value, ttl) {
516
- return this.silgi.options._cacheProvider.set(key, value, ttl);
517
- }
518
- // Add a method to access serviceRegistry entries
519
- getServiceRegistryEntries() {
520
- return Array.from(this.silgi.options._serviceRegistry.entries());
521
- }
522
- // New simpler scope method that just accepts context
523
- createScope(context) {
524
- this.silgi.callHook("request:context", context);
525
- return (scope) => ({
526
- service: (serviceName) => {
527
- const service = this.getService(scope, serviceName);
528
- return {
529
- // Rename 'call' to 'execute'
530
- execute: (methodName, input) => {
531
- return service.execute(methodName, input, {
532
- initSilgi: this,
533
- scope: String(scope),
534
- serviceName: String(serviceName),
535
- methodName: String(methodName),
536
- requestContext: context
537
- });
538
- }
539
- };
540
- }
541
- });
542
- }
543
- setEvent(key, value) {
544
- this.silgi.options._eventContext ??= /* @__PURE__ */ new Map();
545
- this.silgi.options._eventContext.set(key, value);
546
- }
547
- getEvent(key) {
548
- return this.silgi.options._eventContext?.get(key);
549
- }
550
- async buidApp() {
551
- if (this.silgi.options.plugins && !this.silgi.options._pluginManager.isPluginsRegistered()) {
552
- await this.use(this.silgi.options.plugins);
553
- }
554
- }
555
- async addH3App(router) {
556
- if (this.silgi.options.plugins && !this.silgi.options._pluginManager.isPluginsRegistered()) {
557
- await this.use(this.silgi.options.plugins);
558
- }
559
- this.silgi.options.h3Router = router;
560
- await this.silgi.callHook("h3:app:setup", router);
561
- }
562
- }
563
-
564
- function toMethodIdentifier(value) {
565
- return typeof value === "symbol" ? value : String(value);
566
- }
567
- function toServiceIdentifier(value) {
568
- return String(value);
569
- }
570
- function toScopeIdentifier(value) {
571
- return String(value);
572
- }
573
- async function generateCacheKey(params) {
574
- const {
575
- scope,
576
- serviceName,
577
- methodName,
578
- input,
579
- namespace,
580
- keyGenerator,
581
- requestId,
582
- cacheOptions
583
- } = params;
584
- const scopePrefix = cacheOptions?.scope === "request" ? "req" : "global";
585
- const parts = [
586
- scopePrefix,
587
- // Always include scope prefix first
588
- namespace,
589
- toScopeIdentifier(scope),
590
- toServiceIdentifier(serviceName),
591
- toMethodIdentifier(methodName)
592
- ].filter(Boolean);
593
- if (cacheOptions?.scope === "request") {
594
- if (!requestId) {
595
- throw new PergelError({
596
- code: "CACHE_ERROR",
597
- message: "Request ID is required for request-scoped cache"
598
- });
599
- }
600
- parts.push(requestId);
601
- }
602
- if (keyGenerator) {
603
- const customKey = await Promise.resolve(keyGenerator(input));
604
- parts.push(customKey);
605
- } else {
606
- parts.push(typeof input === "object" ? JSON.stringify(input) : String(input));
607
- }
608
- return parts.join(":");
609
- }
610
- function normalizeResult(result) {
611
- if (Array.isArray(result)) {
612
- return [...result];
613
- }
614
- if (result && typeof result === "object") {
615
- if (Object.keys(result).every((key) => !Number.isNaN(Number(key)))) {
616
- return Object.values(result);
617
- }
618
- return { ...result };
619
- }
620
- return result;
621
- }
622
- function createServiceFactory() {
623
- return {
624
- scope(scope) {
625
- return {
626
- service(name, config) {
627
- const methods = /* @__PURE__ */ new Map();
628
- const servicePlugins = config?.plugins || {};
629
- const methodPlugins = {};
630
- return {
631
- methods(methodsConfig) {
632
- Object.entries(methodsConfig).forEach(([methodName, methodConfig]) => {
633
- const typedConfig = methodConfig;
634
- const methodPluginConfig = typedConfig.options?.plugins || {};
635
- methodPlugins[methodName] = Object.entries(methodPluginConfig).reduce((acc, [pluginName, pluginConfig]) => {
636
- const accumulator = acc;
637
- if (typeof pluginConfig === "object" && pluginConfig !== null) {
638
- const servicePluginConf = servicePlugins[pluginName];
639
- accumulator[pluginName] = {
640
- ...typeof servicePluginConf === "object" ? servicePluginConf : {},
641
- ...pluginConfig,
642
- active: pluginConfig.active ?? servicePluginConf?.active ?? false
643
- };
644
- } else {
645
- accumulator[pluginName] = { active: false };
646
- }
647
- return accumulator;
648
- }, {});
649
- methods.set(toMethodIdentifier(methodName), {
650
- handler: typedConfig.handler,
651
- options: {
652
- ...typedConfig.options,
653
- cache: typedConfig.options?.cache ? {
654
- ttl: typedConfig.options.cache.ttl,
655
- scope: typedConfig.options.cache.scope || "request",
656
- key: typedConfig.options.cache.key,
657
- namespace: typedConfig.options.cache.namespace
658
- } : undefined,
659
- plugins: methodPlugins[methodName]
660
- }
661
- });
662
- });
663
- const executor = {
664
- scope: toScopeIdentifier(scope),
665
- name: toServiceIdentifier(name),
666
- handlers: methods,
667
- plugins: servicePlugins,
668
- methodPlugins,
669
- execute: async (methodName, input, context) => {
670
- const handler = methods.get(toMethodIdentifier(methodName));
671
- if (!handler) {
672
- return {
673
- success: false,
674
- error: {
675
- code: "METHOD_NOT_FOUND",
676
- message: `Method ${String(methodName)} not found`
677
- }
678
- };
679
- }
680
- let success = false;
681
- let error;
682
- let result;
683
- const { initSilgi, requestContext } = context;
684
- if (!initSilgi) {
685
- throw new Error("Pergel instance must be provided in context");
686
- }
687
- const cacheKey = handler.options?.cache ? await generateCacheKey({
688
- scope: toScopeIdentifier(scope),
689
- serviceName: toServiceIdentifier(name),
690
- methodName: toMethodIdentifier(methodName),
691
- input,
692
- namespace: handler.options.cache.namespace,
693
- keyGenerator: handler.options.cache.key,
694
- cacheOptions: handler.options.cache,
695
- requestId: context.requestContext.requestId
696
- }) : null;
697
- try {
698
- if (cacheKey) {
699
- const cachedResult = await initSilgi.getFromCache(cacheKey);
700
- if (cachedResult !== null) {
701
- return {
702
- success: true,
703
- data: normalizeResult(result),
704
- cached: false
705
- };
706
- }
707
- }
708
- await initSilgi.silgi.options._pluginManager.runHook("service:beforeExecute", {
709
- scope,
710
- serviceName: String(name),
711
- methodName: String(methodName),
712
- input,
713
- requestContext,
714
- initSilgi,
715
- options: handler.options
716
- });
717
- result = await handler.handler(input, initSilgi.silgi.options.shared, context.requestContext);
718
- success = true;
719
- await initSilgi.silgi.options._pluginManager.runHook("service:afterExecute", {
720
- scope,
721
- serviceName: String(name),
722
- methodName: String(methodName),
723
- input,
724
- result,
725
- requestContext,
726
- initSilgi
727
- });
728
- if (success && cacheKey && handler.options?.cache) {
729
- await initSilgi.setInCache(cacheKey, result, handler.options.cache.ttl);
730
- }
731
- return { success: true, data: normalizeResult(result), cached: false };
732
- } catch (err) {
733
- initSilgi.silgi.logger.error(err);
734
- error = err instanceof Error ? err : new Error("Unknown error");
735
- if (error instanceof PergelError && error.code === "PLUGIN_BLOCKED") {
736
- return {
737
- success: false,
738
- error: {
739
- code: error.code,
740
- message: error.message,
741
- details: error.details
742
- }
743
- };
744
- }
745
- await initSilgi.silgi.options._pluginManager.runHook("app:error", {
746
- scope,
747
- serviceName: String(name),
748
- methodName: String(methodName),
749
- input,
750
- error,
751
- options: handler.options,
752
- timestamp: Date.now(),
753
- initSilgi
754
- });
755
- return {
756
- success: false,
757
- error: error instanceof PergelError ? {
758
- code: error.code,
759
- message: error.message,
760
- details: error.details
761
- } : {
762
- code: "EXECUTION_ERROR",
763
- message: error.message || String(error)
764
- }
765
- };
766
- } finally {
767
- await initSilgi.silgi.options._pluginManager.runHook("app:finalize", {
768
- scope,
769
- serviceName: String(name),
770
- methodName: String(methodName),
771
- input,
772
- result,
773
- success,
774
- error,
775
- requestContext,
776
- initSilgi
777
- });
778
- }
779
- }
780
- };
781
- return executor;
782
- }
783
- };
784
- }
785
- };
786
- }
787
- };
788
- }
789
- function defineService() {
790
- return createServiceFactory();
791
- }
792
- const version = "0.0.1";
793
- function createSilgi(options) {
794
- const hooks = createHooks();
795
- const silgi = {
796
- _version: version,
797
- options,
798
- hooks,
799
- hooksNames: [
800
- "app:error",
801
- "app:finalize",
802
- "plugin:register:after",
803
- "plugin:register:before",
804
- "close",
805
- "plugin:setup:finish",
806
- "ready",
807
- "request:context",
808
- "service:afterExecute",
809
- "service:beforeExecute"
810
- ],
811
- callHook: hooks.callHook,
812
- addHooks: hooks.addHooks,
813
- hook: hooks.hook,
814
- ready: () => {
815
- return hooks.callHook("ready", silgi);
816
- },
817
- close: () => hooks.callHook("close", silgi),
818
- logger: createConsola(options.consolaOptions),
819
- h3Router: options.h3Router
820
- };
821
- if (!options.debug) {
822
- silgi.logger.pauseLogs();
823
- }
824
- const createSilgi2 = new InitSilgi(silgi);
825
- hooks.hookOnce("close", () => {
826
- hooks.removeAllHooks();
827
- });
828
- return createSilgi2;
829
- }
830
- function defineSilgiPlugin(plugin) {
831
- return (options) => {
832
- const pluginWithDefaults = plugin;
833
- pluginWithDefaults.defaults = {
834
- ...plugin.defaults || {},
835
- ...options
836
- };
837
- return pluginWithDefaults;
838
- };
839
- }
840
-
841
- export { defineSilgiPlugin as a, useSilgi as b, createSilgi as c, defineService as d, useHook as e, silgiCtx as s, useShared as u };