silgi 0.0.14 → 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
@@ -0,0 +1,26 @@
1
+ //#region src/core/schema.ts
2
+ var ValidationError = class extends Error {
3
+ issues;
4
+ constructor(options) {
5
+ super(options.message ?? "Validation failed");
6
+ this.name = "ValidationError";
7
+ this.issues = options.issues;
8
+ }
9
+ };
10
+ async function validateSchema(schema, value) {
11
+ const result = await schema["~standard"].validate(value);
12
+ if ("issues" in result && result.issues) throw new ValidationError({ issues: result.issues });
13
+ return result.value;
14
+ }
15
+ function type(...args) {
16
+ const mapFn = args[0];
17
+ return { "~standard": {
18
+ version: 1,
19
+ vendor: "silgi",
20
+ validate(value) {
21
+ return { value: mapFn ? mapFn(value) : value };
22
+ }
23
+ } };
24
+ }
25
+ //#endregion
26
+ export { ValidationError, type, validateSchema };
@@ -0,0 +1,38 @@
1
+ import { createFetchHandler } from "./handler.mjs";
2
+ import { serve } from "srvx";
3
+ //#region src/core/serve.ts
4
+ async function createServeHandler(routerDef, contextFactory, hooks, options) {
5
+ const port = options?.port ?? 3e3;
6
+ const hostname = options?.hostname ?? "127.0.0.1";
7
+ const server = await serve({
8
+ port,
9
+ hostname,
10
+ fetch: createFetchHandler(routerDef, contextFactory, hooks, {
11
+ scalar: options?.scalar,
12
+ analytics: options?.analytics
13
+ }),
14
+ ...options?.http2 && { tls: {
15
+ cert: options.http2.cert,
16
+ key: options.http2.key
17
+ } }
18
+ });
19
+ const url = server.url || `http://${hostname}:${port}`;
20
+ if (options?.ws && server.node?.server) {
21
+ const { attachWebSocket } = await import("../ws.mjs");
22
+ const nodeServer = server.node.server;
23
+ await attachWebSocket(nodeServer, routerDef);
24
+ }
25
+ console.log(`\nSilgi server running at ${url}`);
26
+ if (options?.http2) console.log(` HTTP/2 enabled (with HTTP/1.1 fallback)`);
27
+ if (options?.ws) console.log(` WebSocket RPC at ws://${hostname}:${port}`);
28
+ if (options?.scalar) console.log(` Scalar API Reference at ${url}/reference`);
29
+ if (options?.analytics) console.log(` Analytics dashboard at ${url}/analytics`);
30
+ console.log();
31
+ hooks.callHook("serve:start", {
32
+ url,
33
+ port,
34
+ hostname
35
+ });
36
+ }
37
+ //#endregion
38
+ export { createServeHandler };
@@ -0,0 +1,16 @@
1
+ //#region src/core/sse.d.ts
2
+ interface EventMeta {
3
+ id?: string;
4
+ retry?: number;
5
+ }
6
+ /**
7
+ * Attach SSE metadata (id, retry) to a value transparently.
8
+ * Uses a Proxy so normal property access is unaffected.
9
+ */
10
+ declare function withEventMeta<T>(value: T, meta: EventMeta): T;
11
+ /**
12
+ * Read SSE metadata from a value.
13
+ */
14
+ declare function getEventMeta(value: unknown): EventMeta | undefined;
15
+ //#endregion
16
+ export { EventMeta, getEventMeta, withEventMeta };
@@ -0,0 +1,95 @@
1
+ //#region src/core/sse.ts
2
+ const EVENT_META_SYMBOL = Symbol.for("silgi.event.meta");
3
+ /**
4
+ * Attach SSE metadata (id, retry) to a value transparently.
5
+ * Uses a Proxy so normal property access is unaffected.
6
+ */
7
+ function withEventMeta(value, meta) {
8
+ if (typeof value !== "object" || value === null) return value;
9
+ return new Proxy(value, { get(target, prop, receiver) {
10
+ if (prop === EVENT_META_SYMBOL) return meta;
11
+ return Reflect.get(target, prop, receiver);
12
+ } });
13
+ }
14
+ /**
15
+ * Read SSE metadata from a value.
16
+ */
17
+ function getEventMeta(value) {
18
+ if (typeof value !== "object" || value === null) return void 0;
19
+ return value[EVENT_META_SYMBOL];
20
+ }
21
+ /**
22
+ * Encode an EventMessage into SSE wire format.
23
+ */
24
+ function encodeEventMessage(msg) {
25
+ const lines = [];
26
+ if (msg.comment !== void 0) for (const line of msg.comment.split("\n")) lines.push(`: ${line}`);
27
+ if (msg.event !== void 0) lines.push(`event: ${msg.event}`);
28
+ if (msg.id !== void 0) lines.push(`id: ${msg.id}`);
29
+ if (msg.retry !== void 0) lines.push(`retry: ${msg.retry}`);
30
+ if (msg.data !== void 0) for (const line of msg.data.split("\n")) lines.push(`data: ${line}`);
31
+ return lines.join("\n") + "\n\n";
32
+ }
33
+ /**
34
+ * Convert an async iterator to an SSE ReadableStream.
35
+ * Each yielded value becomes a "message" event.
36
+ * Errors become "error" events. Return value becomes "done".
37
+ */
38
+ function iteratorToEventStream(iterator, options = {}) {
39
+ const serialize = options.serialize ?? JSON.stringify;
40
+ const keepAliveMs = options.keepAliveMs ?? 3e4;
41
+ let keepAliveTimer;
42
+ let cancelled = false;
43
+ return new ReadableStream({
44
+ start(controller) {
45
+ if (options.initialComment !== void 0) controller.enqueue(encodeEventMessage({ comment: options.initialComment }));
46
+ },
47
+ async pull(controller) {
48
+ clearInterval(keepAliveTimer);
49
+ keepAliveTimer = setInterval(() => {
50
+ if (!cancelled) controller.enqueue(encodeEventMessage({ comment: "keepalive" }));
51
+ }, keepAliveMs);
52
+ try {
53
+ const result = await iterator.next();
54
+ clearInterval(keepAliveTimer);
55
+ if (cancelled) return;
56
+ if (result.done) {
57
+ const data = result.value !== void 0 ? serialize(result.value) : void 0;
58
+ controller.enqueue(encodeEventMessage({
59
+ event: "done",
60
+ data
61
+ }));
62
+ controller.close();
63
+ return;
64
+ }
65
+ const meta = getEventMeta(result.value);
66
+ const msg = {
67
+ event: "message",
68
+ data: serialize(result.value),
69
+ id: meta?.id,
70
+ retry: meta?.retry
71
+ };
72
+ controller.enqueue(encodeEventMessage(msg));
73
+ } catch (error) {
74
+ clearInterval(keepAliveTimer);
75
+ if (cancelled) return;
76
+ const errorData = error instanceof Error ? JSON.stringify({
77
+ message: error.message,
78
+ code: error.code
79
+ }) : JSON.stringify({ message: String(error) });
80
+ controller.enqueue(encodeEventMessage({
81
+ event: "error",
82
+ data: errorData
83
+ }));
84
+ controller.close();
85
+ }
86
+ },
87
+ cancel() {
88
+ cancelled = true;
89
+ clearInterval(keepAliveTimer);
90
+ iterator.return?.();
91
+ }
92
+ }).pipeThrough(new TextEncoderStream());
93
+ }
94
+ //#endregion
95
+ export { getEventMeta, iteratorToEventStream, withEventMeta };
@@ -0,0 +1,21 @@
1
+ import { Driver, Storage, StorageValue } from "unstorage";
2
+
3
+ //#region src/core/storage.d.ts
4
+ /** Storage config — map of mount path → driver instance, or a pre-built Storage */
5
+ type StorageConfig = Storage | Record<string, Driver>;
6
+ /**
7
+ * Initialize storage from config — called once at startup.
8
+ * Accepts either a pre-built Storage or a map of mount paths → drivers.
9
+ */
10
+ declare function initStorage(config?: StorageConfig): Storage;
11
+ /**
12
+ * Get the storage instance with optional prefix.
13
+ * Creates default in-memory if not initialized.
14
+ */
15
+ declare function useStorage<T extends StorageValue = StorageValue>(base?: string): Storage<T>;
16
+ /**
17
+ * Reset storage — for testing.
18
+ */
19
+ declare function resetStorage(): void;
20
+ //#endregion
21
+ export { type Driver, type Storage, StorageConfig, type StorageValue, initStorage, resetStorage, useStorage };
@@ -0,0 +1,63 @@
1
+ import { createStorage, prefixStorage } from "unstorage";
2
+ //#region src/core/storage.ts
3
+ /**
4
+ * Storage integration — unstorage with type-safe driver config.
5
+ *
6
+ * Two usage modes:
7
+ *
8
+ * 1. Declarative config (type-safe driver options):
9
+ * ```ts
10
+ * import redisDriver from 'unstorage/drivers/redis'
11
+ * import memoryDriver from 'unstorage/drivers/memory'
12
+ *
13
+ * const s = silgi({
14
+ * context: () => ({}),
15
+ * storage: {
16
+ * cache: redisDriver({ url: 'redis://localhost' }),
17
+ * sessions: memoryDriver(),
18
+ * },
19
+ * })
20
+ * ```
21
+ *
22
+ * 2. Bring your own storage instance:
23
+ * ```ts
24
+ * const storage = createStorage({})
25
+ * storage.mount('cache', redisDriver({ ... }))
26
+ *
27
+ * const s = silgi({
28
+ * context: () => ({}),
29
+ * storage,
30
+ * })
31
+ * ```
32
+ */
33
+ let _storage;
34
+ /**
35
+ * Initialize storage from config — called once at startup.
36
+ * Accepts either a pre-built Storage or a map of mount paths → drivers.
37
+ */
38
+ function initStorage(config) {
39
+ if (_storage) return _storage;
40
+ if (config && "getItem" in config) {
41
+ _storage = config;
42
+ return _storage;
43
+ }
44
+ _storage = createStorage({});
45
+ if (config) for (const [path, driver] of Object.entries(config)) _storage.mount(path, driver);
46
+ return _storage;
47
+ }
48
+ /**
49
+ * Get the storage instance with optional prefix.
50
+ * Creates default in-memory if not initialized.
51
+ */
52
+ function useStorage(base = "") {
53
+ const storage = _storage ?? initStorage();
54
+ return base ? prefixStorage(storage, base) : storage;
55
+ }
56
+ /**
57
+ * Reset storage — for testing.
58
+ */
59
+ function resetStorage() {
60
+ _storage = void 0;
61
+ }
62
+ //#endregion
63
+ export { initStorage, resetStorage, useStorage };
@@ -0,0 +1,21 @@
1
+ //#region src/core/utils.ts
2
+ function sequential(fn) {
3
+ let pending = Promise.resolve();
4
+ return (...args) => {
5
+ const result = pending.then(() => fn(...args), () => fn(...args));
6
+ pending = result;
7
+ return result;
8
+ };
9
+ }
10
+ function parseEmptyableJSON(text) {
11
+ if (text === "") return void 0;
12
+ return JSON.parse(text);
13
+ }
14
+ function stringifyJSON(value) {
15
+ return JSON.stringify(value, (_key, val) => {
16
+ if (typeof val === "bigint") return val.toString();
17
+ return val;
18
+ });
19
+ }
20
+ //#endregion
21
+ export { parseEmptyableJSON, sequential, stringifyJSON };
@@ -0,0 +1,125 @@
1
+ //#region src/fast-stringify.ts
2
+ /**
3
+ * Compile a schema into a fast stringify function.
4
+ * Falls back to JSON.stringify for unknown/complex schemas.
5
+ */
6
+ function compileStringify(schema) {
7
+ if (!schema) return JSON.stringify;
8
+ const def = getZodDef(schema);
9
+ if (!def) return JSON.stringify;
10
+ return compileType(def) ?? JSON.stringify;
11
+ }
12
+ function getZodDef(schema) {
13
+ return schema?._zod?.def ?? schema?._def;
14
+ }
15
+ function compileType(def) {
16
+ switch (def.type ?? def.typeName) {
17
+ case "string":
18
+ case "ZodString": return (v) => "\"" + escapeString(v) + "\"";
19
+ case "number":
20
+ case "ZodNumber":
21
+ case "int": return (v) => String(v);
22
+ case "boolean":
23
+ case "ZodBoolean": return (v) => v ? "true" : "false";
24
+ case "null":
25
+ case "ZodNull": return () => "null";
26
+ case "literal":
27
+ case "ZodLiteral": {
28
+ const values = def.values ?? [def.value];
29
+ const cached = JSON.stringify(values[0]);
30
+ return () => cached;
31
+ }
32
+ case "object":
33
+ case "ZodObject": return compileObject(def);
34
+ case "array":
35
+ case "ZodArray": return;
36
+ case "optional":
37
+ case "ZodOptional":
38
+ case "nullable":
39
+ case "ZodNullable": {
40
+ const inner = compileType(getZodDef(def.innerType ?? def.wrapped));
41
+ if (!inner) return void 0;
42
+ return (v) => v == null ? "null" : inner(v);
43
+ }
44
+ case "default":
45
+ case "ZodDefault": return compileType(getZodDef(def.innerType ?? def.wrapped)) ?? void 0;
46
+ default: return;
47
+ }
48
+ }
49
+ function compileObject(def) {
50
+ const shape = def.shape ?? (typeof def.shape === "function" ? def.shape() : void 0);
51
+ if (!shape) return void 0;
52
+ const entries = Object.entries(shape);
53
+ if (entries.length === 0) return () => "{}";
54
+ if (entries.length > 20) return void 0;
55
+ const propCompilers = [];
56
+ for (const [key, propSchema] of entries) {
57
+ const propDef = getZodDef(propSchema);
58
+ if (!propDef) return void 0;
59
+ const propType = propDef.type ?? propDef.typeName;
60
+ const isOptional = propType === "optional" || propType === "ZodOptional" || propType === "nullable" || propType === "ZodNullable";
61
+ const propFn = compileType(propDef);
62
+ if (!propFn) return void 0;
63
+ propCompilers.push({
64
+ key,
65
+ jsonKey: "\"" + escapeString(key) + "\":",
66
+ stringify: propFn,
67
+ optional: isOptional
68
+ });
69
+ }
70
+ if (propCompilers.every((p) => !p.optional) && propCompilers.length <= 8) return buildUnrolledObjectFn(propCompilers);
71
+ return (obj) => {
72
+ let result = "{";
73
+ let first = true;
74
+ for (const prop of propCompilers) {
75
+ const val = obj[prop.key];
76
+ if (prop.optional && val === void 0) continue;
77
+ if (!first) result += ",";
78
+ result += prop.jsonKey + prop.stringify(val);
79
+ first = false;
80
+ }
81
+ return result + "}";
82
+ };
83
+ }
84
+ function buildUnrolledObjectFn(props) {
85
+ return (obj) => {
86
+ let s = "{";
87
+ for (let i = 0; i < props.length; i++) {
88
+ const p = props[i];
89
+ if (i > 0) s += ",";
90
+ s += p.jsonKey + p.stringify(obj[p.key]);
91
+ }
92
+ return s + "}";
93
+ };
94
+ }
95
+ const ESCAPE_CHARS = {
96
+ "\"": "\\\"",
97
+ "\\": "\\\\",
98
+ "\b": "\\b",
99
+ "\f": "\\f",
100
+ "\n": "\\n",
101
+ "\r": "\\r",
102
+ " ": "\\t"
103
+ };
104
+ function escapeString(str) {
105
+ let needsEscape = false;
106
+ for (let i = 0; i < str.length; i++) {
107
+ const code = str.charCodeAt(i);
108
+ if (code < 32 || code === 34 || code === 92) {
109
+ needsEscape = true;
110
+ break;
111
+ }
112
+ }
113
+ if (!needsEscape) return str;
114
+ let result = "";
115
+ for (let i = 0; i < str.length; i++) {
116
+ const ch = str[i];
117
+ const escaped = ESCAPE_CHARS[ch];
118
+ if (escaped) result += escaped;
119
+ else if (str.charCodeAt(i) < 32) result += "\\u" + str.charCodeAt(i).toString(16).padStart(4, "0");
120
+ else result += ch;
121
+ }
122
+ return result;
123
+ }
124
+ //#endregion
125
+ export { compileStringify };
package/dist/index.d.mts CHANGED
@@ -1,37 +1,15 @@
1
- import { D as DefaultContext, a as DefaultInterface, E as ExtractScope, S as ServicePluginConfig, b as ServiceMethod, c as ExtractShared, C as CacheScope, d as CacheKeyGenerator, M as MethodPluginConfig, e as ServiceExecutor, O as OmitSilgiOptions, I as InitSilgi, P as PergelPlugin, f as Silgi } from './shared/silgi.D5qK9QOm.mjs';
2
- export { h as DefaultHooks, g as InitializedCreateScope, k as SchemaGenerated, i as SilgiDefaultContext, j as SilgiDefaultInterface } from './shared/silgi.D5qK9QOm.mjs';
3
- import * as unctx from 'unctx';
4
- import 'consola';
5
- import 'h3';
6
- import 'zod';
7
- import 'hookable';
8
-
9
- declare function defineService<TContext extends DefaultContext = DefaultContext, TInterface extends DefaultInterface = DefaultInterface>(): {
10
- scope<TScope extends keyof ExtractScope<TInterface>>(scope: TScope): {
11
- service<TService extends keyof ExtractScope<TInterface>[TScope]>(name: TService, config?: ServicePluginConfig<TInterface> | undefined): {
12
- methods<TMethods extends { [K in keyof ExtractScope<TInterface>[TScope][TService]]: {
13
- handler: (input: ExtractScope<TInterface>[TScope][TService][K] extends ServiceMethod<infer I, any, DefaultInterface> ? I : never, shared: ExtractShared<TInterface>, context: TContext) => Promise<ExtractScope<TInterface>[TScope][TService][K] extends ServiceMethod<any, infer O, DefaultInterface> ? O : never>;
14
- options?: {
15
- cache?: {
16
- ttl: number;
17
- scope?: CacheScope;
18
- key?: CacheKeyGenerator<any>;
19
- namespace?: string;
20
- } | undefined;
21
- plugins?: MethodPluginConfig<TInterface> | undefined;
22
- } | undefined;
23
- }; }>(methodsConfig: TMethods): ServiceExecutor<ExtractScope<TInterface>[TScope][TService], TContext, TInterface>;
24
- };
25
- };
26
- };
27
- declare function createSilgi<TContext extends DefaultContext, TInterface extends DefaultInterface>(options: OmitSilgiOptions<TContext, TInterface>): InitSilgi<TContext, TInterface>;
28
- declare function defineSilgiPlugin<TPluginConfig, TContext extends DefaultContext = DefaultContext, TInterface extends DefaultInterface = DefaultInterface>(plugin: Omit<PergelPlugin<TContext, TInterface, TPluginConfig>, 'defaults'> & {
29
- defaults?: TPluginConfig;
30
- }): (options?: TPluginConfig) => PergelPlugin<TContext, TInterface, TPluginConfig>;
31
-
32
- declare const silgiCtx: unctx.UseContext<InitSilgi<DefaultContext, DefaultInterface>>;
33
- declare function useShared<TContext extends DefaultContext, TInterface extends DefaultInterface>(): Silgi<TContext, TInterface>["options"]["shared"];
34
- declare function useSilgi(): InitSilgi<DefaultContext, DefaultInterface>;
35
- declare function useHook<TContext extends DefaultContext, TInterface extends DefaultInterface>(): Silgi<TContext, TInterface>["hooks"]["hook"];
36
-
37
- export { DefaultContext, DefaultInterface, InitSilgi, OmitSilgiOptions, createSilgi, defineService, defineSilgiPlugin, silgiCtx, useHook, useShared, useSilgi };
1
+ import { AnySchema, InferSchemaInput, InferSchemaOutput, Schema, ValidationError, type, validateSchema } from "./core/schema.mjs";
2
+ import { ErrorDef, ErrorDefItem, FailFn, GuardDef, GuardFn, InferClient, InferContextFromUse, InferGuardOutput, Meta, MiddlewareDef, ProcedureDef, ProcedureType, ResolveContext, RouterDef, WrapDef, WrapFn } from "./types.mjs";
3
+ import { SilgiError, SilgiErrorCode, SilgiErrorJSON, SilgiErrorOptions, isDefinedError, toSilgiError } from "./core/error.mjs";
4
+ import { ProcedureBuilder, ProcedureBuilderWithOutput } from "./builder.mjs";
5
+ import { Driver, Storage, StorageConfig, StorageValue, initStorage, resetStorage, useStorage } from "./core/storage.mjs";
6
+ import { ScalarOptions, generateOpenAPI, scalarHTML } from "./scalar.mjs";
7
+ import { SilgiConfig, SilgiInstance, silgi } from "./silgi.mjs";
8
+ import { AsyncIteratorClass, mapAsyncIterator } from "./core/iterator.mjs";
9
+ import { EventMeta, getEventMeta, withEventMeta } from "./core/sse.mjs";
10
+ import { CallableOptions, callable } from "./callable.mjs";
11
+ import { LifecycleHooks, lifecycleWrap } from "./lifecycle.mjs";
12
+ import { mapInput } from "./map-input.mjs";
13
+ import { ContextPool, compileProcedure, compileRouter } from "./compile.mjs";
14
+ import { LazyRouter, isLazy, lazy, resolveLazy } from "./lazy.mjs";
15
+ export { type AnySchema, AsyncIteratorClass, type CallableOptions, ContextPool, type Driver, type ErrorDef, type ErrorDefItem, type EventMeta, type FailFn, type GuardDef, type GuardFn, type InferClient, type InferContextFromUse, type InferGuardOutput, type InferSchemaInput, type InferSchemaOutput, type LazyRouter, type LifecycleHooks, type Meta, type MiddlewareDef, type ProcedureBuilder, type ProcedureBuilderWithOutput, type ProcedureDef, type ProcedureType, type ResolveContext, type RouterDef, type ScalarOptions, type Schema, type SilgiConfig, SilgiError, type SilgiErrorCode, type SilgiErrorJSON, type SilgiErrorOptions, type SilgiInstance, type Storage, type StorageConfig, type StorageValue, ValidationError, type WrapDef, type WrapFn, callable, compileProcedure, compileRouter, generateOpenAPI, getEventMeta, initStorage, isDefinedError, isLazy, lazy, lifecycleWrap, mapAsyncIterator, mapInput, resetStorage, resolveLazy, scalarHTML, silgi, toSilgiError, type, useStorage, validateSchema, withEventMeta };
package/dist/index.mjs CHANGED
@@ -1,7 +1,13 @@
1
- export { c as createSilgi, d as defineService, a as defineSilgiPlugin, s as silgiCtx, e as useHook, u as useShared, b as useSilgi } from './shared/silgi.BMCYk2cR.mjs';
2
- import 'consola';
3
- import 'hookable';
4
- import 'node:buffer';
5
- import 'node:fs';
6
- import 'node:path';
7
- import 'unctx';
1
+ import { SilgiError, isDefinedError, toSilgiError } from "./core/error.mjs";
2
+ import { ValidationError, type, validateSchema } from "./core/schema.mjs";
3
+ import { ContextPool, compileProcedure, compileRouter } from "./compile.mjs";
4
+ import { generateOpenAPI, scalarHTML } from "./scalar.mjs";
5
+ import { AsyncIteratorClass, mapAsyncIterator } from "./core/iterator.mjs";
6
+ import { getEventMeta, withEventMeta } from "./core/sse.mjs";
7
+ import { silgi } from "./silgi.mjs";
8
+ import { callable } from "./callable.mjs";
9
+ import { lifecycleWrap } from "./lifecycle.mjs";
10
+ import { mapInput } from "./map-input.mjs";
11
+ import { isLazy, lazy, resolveLazy } from "./lazy.mjs";
12
+ import { initStorage, resetStorage, useStorage } from "./core/storage.mjs";
13
+ export { AsyncIteratorClass, ContextPool, SilgiError, ValidationError, callable, compileProcedure, compileRouter, generateOpenAPI, getEventMeta, initStorage, isDefinedError, isLazy, lazy, lifecycleWrap, mapAsyncIterator, mapInput, resetStorage, resolveLazy, scalarHTML, silgi, toSilgiError, type, useStorage, validateSchema, withEventMeta };
@@ -0,0 +1,25 @@
1
+ import { ProcedureDef, RouterDef } from "../../types.mjs";
2
+
3
+ //#region src/integrations/ai/index.d.ts
4
+ /**
5
+ * Convert a single silgi procedure into an AI SDK tool.
6
+ */
7
+ declare function procedureToTool(name: string, procedure: ProcedureDef, options?: {
8
+ description?: string;
9
+ }): any;
10
+ /**
11
+ * Convert all procedures in a silgi router into AI SDK tools.
12
+ * Nested routers are flattened with underscore separators.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // Router: { users: { list, create }, health }
17
+ * // Tools: { users_list, users_create, health }
18
+ * ```
19
+ */
20
+ declare function routerToTools(router: RouterDef, options?: {
21
+ /** Filter which procedures to expose as tools */filter?: (path: string, procedure: ProcedureDef) => boolean; /** Custom descriptions per path */
22
+ descriptions?: Record<string, string>;
23
+ }): Record<string, any>;
24
+ //#endregion
25
+ export { procedureToTool, routerToTools };
@@ -0,0 +1,116 @@
1
+ import { compileProcedure } from "../../compile.mjs";
2
+ import { jsonSchema, tool } from "ai";
3
+ //#region src/integrations/ai/index.ts
4
+ /**
5
+ * Vercel AI SDK integration — expose silgi procedures as AI tools.
6
+ *
7
+ * Converts silgi router procedures into AI SDK tools that can be
8
+ * called by LLMs via function calling / tool use.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { generateText } from "ai"
13
+ * import { openai } from "@ai-sdk/openai"
14
+ * import { routerToTools } from "silgi/ai"
15
+ *
16
+ * const tools = routerToTools(appRouter)
17
+ *
18
+ * const { text } = await generateText({
19
+ * model: openai("gpt-4o"),
20
+ * tools,
21
+ * prompt: "List all users with limit 5",
22
+ * })
23
+ * ```
24
+ */
25
+ /**
26
+ * Convert a single silgi procedure into an AI SDK tool.
27
+ */
28
+ function procedureToTool(name, procedure, options) {
29
+ const handler = compileProcedure(procedure);
30
+ const signal = new AbortController().signal;
31
+ return tool({
32
+ description: options?.description ?? procedure.route?.description ?? procedure.route?.summary ?? `Call ${name}`,
33
+ parameters: jsonSchema(procedure.input ? zodToJsonSchemaSimple(procedure.input) : {
34
+ type: "object",
35
+ properties: {}
36
+ }),
37
+ execute: async (input) => {
38
+ const result = handler(Object.create(null), input ?? {}, signal);
39
+ return result instanceof Promise ? await result : result;
40
+ }
41
+ });
42
+ }
43
+ /**
44
+ * Convert all procedures in a silgi router into AI SDK tools.
45
+ * Nested routers are flattened with underscore separators.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * // Router: { users: { list, create }, health }
50
+ * // Tools: { users_list, users_create, health }
51
+ * ```
52
+ */
53
+ function routerToTools(router, options) {
54
+ const tools = {};
55
+ collectProcedures(router, [], (path, proc) => {
56
+ const flatName = path.join("_");
57
+ if (options?.filter && !options.filter(flatName, proc)) return;
58
+ tools[flatName] = procedureToTool(flatName, proc, { description: options?.descriptions?.[flatName] });
59
+ });
60
+ return tools;
61
+ }
62
+ function isProcedureDef(v) {
63
+ return typeof v === "object" && v !== null && "type" in v && "resolve" in v;
64
+ }
65
+ function collectProcedures(node, path, cb) {
66
+ if (isProcedureDef(node)) {
67
+ cb(path, node);
68
+ return;
69
+ }
70
+ if (typeof node === "object" && node !== null) for (const [key, child] of Object.entries(node)) collectProcedures(child, [...path, key], cb);
71
+ }
72
+ /** Simple Zod → JSON Schema for AI tool parameters */
73
+ function zodToJsonSchemaSimple(schema) {
74
+ const zod = schema?._zod ?? schema?._def;
75
+ if (!zod) return {
76
+ type: "object",
77
+ properties: {}
78
+ };
79
+ return convertDef(zod.def ?? zod);
80
+ }
81
+ function convertDef(def) {
82
+ if (!def) return {};
83
+ switch (def.type ?? def.typeName) {
84
+ case "string": return { type: "string" };
85
+ case "number":
86
+ case "float": return { type: "number" };
87
+ case "int": return { type: "integer" };
88
+ case "boolean": return { type: "boolean" };
89
+ case "object": {
90
+ const props = {};
91
+ const required = [];
92
+ if (def.shape) for (const [k, v] of Object.entries(def.shape)) {
93
+ props[k] = zodToJsonSchemaSimple(v);
94
+ const fz = v?._zod?.def ?? v?._def;
95
+ if (fz?.type !== "optional" && fz?.typeName !== "ZodOptional") required.push(k);
96
+ }
97
+ return {
98
+ type: "object",
99
+ properties: props,
100
+ ...required.length ? { required } : {}
101
+ };
102
+ }
103
+ case "array": return {
104
+ type: "array",
105
+ ...def.element ? { items: zodToJsonSchemaSimple(def.element) } : {}
106
+ };
107
+ case "optional": return zodToJsonSchemaSimple(def.innerType ?? def.inner);
108
+ case "enum": return {
109
+ type: "string",
110
+ enum: def.values ?? def.entries
111
+ };
112
+ default: return {};
113
+ }
114
+ }
115
+ //#endregion
116
+ export { procedureToTool, routerToTools };