@spfn/core 0.1.0-alpha.86 → 0.2.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 (71) hide show
  1. package/README.md +1046 -384
  2. package/dist/boss-D-fGtVgM.d.ts +187 -0
  3. package/dist/cache/index.d.ts +13 -33
  4. package/dist/cache/index.js +14 -703
  5. package/dist/cache/index.js.map +1 -1
  6. package/dist/codegen/index.d.ts +167 -17
  7. package/dist/codegen/index.js +76 -1419
  8. package/dist/codegen/index.js.map +1 -1
  9. package/dist/config/index.d.ts +1191 -0
  10. package/dist/config/index.js +264 -0
  11. package/dist/config/index.js.map +1 -0
  12. package/dist/db/index.d.ts +728 -59
  13. package/dist/db/index.js +1028 -1225
  14. package/dist/db/index.js.map +1 -1
  15. package/dist/env/index.d.ts +579 -308
  16. package/dist/env/index.js +438 -930
  17. package/dist/env/index.js.map +1 -1
  18. package/dist/errors/index.d.ts +417 -29
  19. package/dist/errors/index.js +359 -98
  20. package/dist/errors/index.js.map +1 -1
  21. package/dist/event/index.d.ts +108 -0
  22. package/dist/event/index.js +122 -0
  23. package/dist/event/index.js.map +1 -0
  24. package/dist/job/index.d.ts +172 -0
  25. package/dist/job/index.js +361 -0
  26. package/dist/job/index.js.map +1 -0
  27. package/dist/logger/index.d.ts +20 -79
  28. package/dist/logger/index.js +82 -387
  29. package/dist/logger/index.js.map +1 -1
  30. package/dist/middleware/index.d.ts +2 -11
  31. package/dist/middleware/index.js +49 -703
  32. package/dist/middleware/index.js.map +1 -1
  33. package/dist/nextjs/index.d.ts +120 -0
  34. package/dist/nextjs/index.js +416 -0
  35. package/dist/nextjs/index.js.map +1 -0
  36. package/dist/{client/nextjs/index.d.ts → nextjs/server.d.ts} +288 -262
  37. package/dist/nextjs/server.js +568 -0
  38. package/dist/nextjs/server.js.map +1 -0
  39. package/dist/route/index.d.ts +667 -25
  40. package/dist/route/index.js +437 -1287
  41. package/dist/route/index.js.map +1 -1
  42. package/dist/route/types.d.ts +38 -0
  43. package/dist/route/types.js +3 -0
  44. package/dist/route/types.js.map +1 -0
  45. package/dist/server/index.d.ts +201 -67
  46. package/dist/server/index.js +921 -3182
  47. package/dist/server/index.js.map +1 -1
  48. package/dist/types-BGl4QL1w.d.ts +77 -0
  49. package/dist/types-DRG2XMTR.d.ts +157 -0
  50. package/package.json +56 -48
  51. package/dist/auto-loader-JFaZ9gON.d.ts +0 -80
  52. package/dist/client/index.d.ts +0 -358
  53. package/dist/client/index.js +0 -357
  54. package/dist/client/index.js.map +0 -1
  55. package/dist/client/nextjs/index.js +0 -371
  56. package/dist/client/nextjs/index.js.map +0 -1
  57. package/dist/codegen/generators/index.d.ts +0 -19
  58. package/dist/codegen/generators/index.js +0 -1404
  59. package/dist/codegen/generators/index.js.map +0 -1
  60. package/dist/database-errors-BNNmLTJE.d.ts +0 -86
  61. package/dist/events/index.d.ts +0 -183
  62. package/dist/events/index.js +0 -77
  63. package/dist/events/index.js.map +0 -1
  64. package/dist/index-DHiAqhKv.d.ts +0 -101
  65. package/dist/index.d.ts +0 -8
  66. package/dist/index.js +0 -3674
  67. package/dist/index.js.map +0 -1
  68. package/dist/types/index.d.ts +0 -121
  69. package/dist/types/index.js +0 -38
  70. package/dist/types/index.js.map +0 -1
  71. package/dist/types-BXibIEyj.d.ts +0 -60
@@ -1,77 +0,0 @@
1
- // src/events/adapters/memory.ts
2
- var InMemoryEventEmitter = class {
3
- listeners = /* @__PURE__ */ new Map();
4
- on(event, handler) {
5
- if (!this.listeners.has(event)) {
6
- this.listeners.set(event, []);
7
- }
8
- this.listeners.get(event).push(handler);
9
- }
10
- async emit(event, data) {
11
- const handlers = this.listeners.get(event) || [];
12
- if (handlers.length === 0) {
13
- return;
14
- }
15
- const results = await Promise.allSettled(
16
- handlers.map(async (handler) => {
17
- try {
18
- return await handler(data);
19
- } catch (error) {
20
- throw error;
21
- }
22
- })
23
- );
24
- const failed = results.filter((r) => r.status === "rejected");
25
- if (failed.length > 0) {
26
- console.error(
27
- `[Events] ${failed.length}/${handlers.length} handlers failed for event "${event}"`,
28
- {
29
- errors: failed.map((r) => r.reason)
30
- }
31
- );
32
- }
33
- }
34
- off(event) {
35
- this.listeners.delete(event);
36
- }
37
- clear() {
38
- this.listeners.clear();
39
- }
40
- /**
41
- * Get list of registered events (for debugging)
42
- */
43
- getEvents() {
44
- return Array.from(this.listeners.keys());
45
- }
46
- /**
47
- * Get number of handlers for an event (for debugging)
48
- */
49
- getHandlerCount(event) {
50
- return this.listeners.get(event)?.length || 0;
51
- }
52
- };
53
-
54
- // src/events/emitter.ts
55
- var emitter = new InMemoryEventEmitter();
56
- function setEventEmitter(adapter) {
57
- emitter = adapter;
58
- }
59
- function getEventEmitter() {
60
- return emitter;
61
- }
62
- function on(event, handler) {
63
- emitter.on(event, handler);
64
- }
65
- async function emit(event, data) {
66
- await emitter.emit(event, data);
67
- }
68
- function off(event) {
69
- emitter.off(event);
70
- }
71
- function clear() {
72
- emitter.clear();
73
- }
74
-
75
- export { InMemoryEventEmitter, clear, emit, getEventEmitter, off, on, setEventEmitter };
76
- //# sourceMappingURL=index.js.map
77
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/events/adapters/memory.ts","../../src/events/emitter.ts"],"names":[],"mappings":";AAsBO,IAAM,uBAAN,MACP;AAAA,EACY,SAAA,uBAAgB,GAAA,EAA4B;AAAA,EAEpD,EAAA,CAAG,OAAe,OAAA,EAClB;AACI,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA,EAC7B;AACI,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA;AAAA,IAChC;AACA,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA,CAAG,KAAK,OAAO,CAAA;AAAA,EAC3C;AAAA,EAEA,MAAM,IAAA,CAAK,KAAA,EAAe,IAAA,EAC1B;AACI,IAAA,MAAM,WAAW,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,KAAK,EAAC;AAE/C,IAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EACxB;AACI,MAAA;AAAA,IACJ;AAIA,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA;AAAA,MAC1B,QAAA,CAAS,GAAA,CAAI,OAAO,OAAA,KACpB;AACI,QAAA,IACA;AACI,UAAA,OAAO,MAAM,QAAQ,IAAI,CAAA;AAAA,QAC7B,SACO,KAAA,EACP;AAEI,UAAA,MAAM,KAAA;AAAA,QACV;AAAA,MACJ,CAAC;AAAA,KACL;AAGA,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,WAAW,UAAU,CAAA;AAC1D,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EACpB;AACI,MAAA,OAAA,CAAQ,KAAA;AAAA,QACJ,YAAY,MAAA,CAAO,MAAM,IAAI,QAAA,CAAS,MAAM,+BAA+B,KAAK,CAAA,CAAA,CAAA;AAAA,QAChF;AAAA,UACI,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAM,EAA4B,MAAM;AAAA;AAC/D,OACJ;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,IAAI,KAAA,EACJ;AACI,IAAA,IAAA,CAAK,SAAA,CAAU,OAAO,KAAK,CAAA;AAAA,EAC/B;AAAA,EAEA,KAAA,GACA;AACI,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GACA;AACI,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,KAAA,EAChB;AACI,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,GAAG,MAAA,IAAU,CAAA;AAAA,EAChD;AACJ;;;AC7DA,IAAI,OAAA,GAAwB,IAAI,oBAAA,EAAqB;AAe9C,SAAS,gBAAgB,OAAA,EAChC;AACI,EAAA,OAAA,GAAU,OAAA;AACd;AAOO,SAAS,eAAA,GAChB;AACI,EAAA,OAAO,OAAA;AACX;AAeO,SAAS,EAAA,CAAG,OAAe,OAAA,EAClC;AACI,EAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,OAAO,CAAA;AAC7B;AAgBA,eAAsB,IAAA,CAAK,OAAe,IAAA,EAC1C;AACI,EAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,IAAI,CAAA;AAClC;AAYO,SAAS,IAAI,KAAA,EACpB;AACI,EAAA,OAAA,CAAQ,IAAI,KAAK,CAAA;AACrB;AAeO,SAAS,KAAA,GAChB;AACI,EAAA,OAAA,CAAQ,KAAA,EAAM;AAClB","file":"index.js","sourcesContent":["/**\n * In-Memory Event Emitter\n *\n * Simple in-process event emitter for single-instance deployments.\n * Events are not shared across multiple server instances.\n *\n * Use this adapter for:\n * - Development\n * - Single-instance production deployments\n * - When you don't need distributed events\n *\n * @example\n * ```typescript\n * import { setEventEmitter } from '@spfn/core/events';\n * import { InMemoryEventEmitter } from '@spfn/core/events/adapters';\n *\n * setEventEmitter(new InMemoryEventEmitter());\n * ```\n */\n\nimport type { EventEmitter, EventHandler } from '../types';\n\nexport class InMemoryEventEmitter implements EventEmitter\n{\n private listeners = new Map<string, EventHandler[]>();\n\n on(event: string, handler: EventHandler): void\n {\n if (!this.listeners.has(event))\n {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)!.push(handler);\n }\n\n async emit(event: string, data?: any): Promise<void>\n {\n const handlers = this.listeners.get(event) || [];\n\n if (handlers.length === 0)\n {\n return;\n }\n\n // Execute all handlers in parallel\n // Failures in individual handlers don't affect others\n const results = await Promise.allSettled(\n handlers.map(async (handler) =>\n {\n try\n {\n return await handler(data);\n }\n catch (error)\n {\n // Catch and re-throw for Promise.allSettled\n throw error;\n }\n })\n );\n\n // Log failed handlers for debugging\n const failed = results.filter(r => r.status === 'rejected');\n if (failed.length > 0)\n {\n console.error(\n `[Events] ${failed.length}/${handlers.length} handlers failed for event \"${event}\"`,\n {\n errors: failed.map(r => (r as PromiseRejectedResult).reason),\n }\n );\n }\n }\n\n off(event: string): void\n {\n this.listeners.delete(event);\n }\n\n clear(): void\n {\n this.listeners.clear();\n }\n\n /**\n * Get list of registered events (for debugging)\n */\n getEvents(): string[]\n {\n return Array.from(this.listeners.keys());\n }\n\n /**\n * Get number of handlers for an event (for debugging)\n */\n getHandlerCount(event: string): number\n {\n return this.listeners.get(event)?.length || 0;\n }\n}","/**\n * Event Emitter\n *\n * Adapter-based event emitter for decoupled communication between packages.\n *\n * Default adapter: InMemoryEventEmitter (single-instance)\n *\n * @example\n * ```typescript\n * // Subscribe to events\n * import { on } from '@spfn/core/events';\n *\n * on('user:created', async (data) => {\n * console.log('User created:', data.email);\n * });\n *\n * // Emit events\n * import { emit } from '@spfn/core/events';\n *\n * await emit('user:created', {\n * userId: '123',\n * email: 'user@example.com'\n * });\n *\n * // Switch to Redis adapter (multi-instance)\n * import { setEventEmitter } from '@spfn/core/events';\n * import { RedisEventEmitter } from '@spfn/core/events/adapters';\n *\n * setEventEmitter(new RedisEventEmitter({\n * host: 'localhost',\n * port: 6379\n * }));\n * ```\n */\n\nimport type { EventEmitter, EventHandler } from './types';\nimport { InMemoryEventEmitter } from './adapters/memory';\n\nlet emitter: EventEmitter = new InMemoryEventEmitter();\n\n/**\n * Set the event emitter adapter\n *\n * @param adapter - EventEmitter adapter implementation\n *\n * @example\n * ```typescript\n * import { setEventEmitter } from '@spfn/core/events';\n * import { InMemoryEventEmitter } from '@spfn/core/events/adapters';\n *\n * setEventEmitter(new InMemoryEventEmitter());\n * ```\n */\nexport function setEventEmitter(adapter: EventEmitter): void\n{\n emitter = adapter;\n}\n\n/**\n * Get the current event emitter adapter\n *\n * @returns Current EventEmitter instance\n */\nexport function getEventEmitter(): EventEmitter\n{\n return emitter;\n}\n\n/**\n * Subscribe to an event\n *\n * @param event - Event name\n * @param handler - Event handler function\n *\n * @example\n * ```typescript\n * on('user:created', async (data) => {\n * console.log('User created:', data.email);\n * });\n * ```\n */\nexport function on(event: string, handler: EventHandler): void\n{\n emitter.on(event, handler);\n}\n\n/**\n * Emit an event\n *\n * @param event - Event name\n * @param data - Event data\n *\n * @example\n * ```typescript\n * await emit('user:created', {\n * userId: '123',\n * email: 'user@example.com'\n * });\n * ```\n */\nexport async function emit(event: string, data?: any): Promise<void>\n{\n await emitter.emit(event, data);\n}\n\n/**\n * Unsubscribe from an event\n *\n * @param event - Event name\n *\n * @example\n * ```typescript\n * off('user:created');\n * ```\n */\nexport function off(event: string): void\n{\n emitter.off(event);\n}\n\n/**\n * Clear all event subscriptions\n *\n * Useful for testing or cleanup\n *\n * @example\n * ```typescript\n * // In tests\n * beforeEach(() => {\n * clear();\n * });\n * ```\n */\nexport function clear(): void\n{\n emitter.clear();\n}"]}
@@ -1,101 +0,0 @@
1
- /**
2
- * Generator Interface
3
- *
4
- * Defines the contract for code generators that can be orchestrated by the codegen system.
5
- */
6
- /**
7
- * Generator execution trigger types
8
- */
9
- type GeneratorTrigger = 'watch' | 'manual' | 'build' | 'start';
10
- interface GeneratorOptions {
11
- /** Project root directory */
12
- cwd: string;
13
- /** Enable debug logging */
14
- debug?: boolean;
15
- /** Execution trigger information */
16
- trigger?: {
17
- /** How the generator was triggered */
18
- type: GeneratorTrigger;
19
- /** Changed file information (only for 'watch' trigger) */
20
- changedFile?: {
21
- path: string;
22
- event: 'add' | 'change' | 'unlink';
23
- };
24
- };
25
- /** Custom configuration options */
26
- [key: string]: any;
27
- }
28
- interface Generator {
29
- /** Unique generator name */
30
- name: string;
31
- /** File patterns to watch (glob patterns) */
32
- watchPatterns: string[];
33
- /**
34
- * When this generator should run
35
- *
36
- * @default ['watch', 'manual', 'build']
37
- *
38
- * Examples:
39
- * - ['watch', 'build']: Run during development and build (e.g., admin-nav-generator)
40
- * - ['build', 'start']: Run during build and server start (e.g., db-migration)
41
- * - ['watch', 'manual']: Run during development and manual CLI (e.g., contract-generator)
42
- * - ['start']: Run only on server start (e.g., runtime config generator)
43
- */
44
- runOn?: GeneratorTrigger[];
45
- /**
46
- * Generate code
47
- *
48
- * Generator can implement incremental updates by checking `options.trigger.changedFile`.
49
- * If incremental update is not possible, do full regeneration.
50
- *
51
- * @param options - Generator options with trigger context
52
- *
53
- * @example
54
- * ```typescript
55
- * async generate(options: GeneratorOptions): Promise<void>
56
- * {
57
- * // Check if incremental update is possible
58
- * if (options.trigger?.changedFile)
59
- * {
60
- * const { path, event } = options.trigger.changedFile;
61
- *
62
- * if (canDoIncrementalUpdate(path, event))
63
- * {
64
- * await updateSingleFile(path);
65
- * return;
66
- * }
67
- * }
68
- *
69
- * // Fallback: full regeneration
70
- * await fullRegenerate();
71
- * }
72
- * ```
73
- */
74
- generate(options: GeneratorOptions): Promise<void>;
75
- }
76
-
77
- /**
78
- * Contract Generator
79
- *
80
- * Generates type-safe API client from contract definitions
81
- *
82
- * Features:
83
- * - Automatic scanning of contract files
84
- * - Type-safe client generation with InferContract
85
- * - Split output by resource for better code organization
86
- * - Incremental updates when single files change (smart regeneration)
87
- */
88
-
89
- interface ContractGeneratorConfig {
90
- /** Contracts directory (default: src/lib/contracts) */
91
- contractsDir?: string;
92
- /** Output directory (default: src/lib/api) */
93
- outputPath?: string;
94
- /** Base URL for API client */
95
- baseUrl?: string;
96
- /** When to run this generator (default: ['watch', 'manual', 'build']) */
97
- runOn?: GeneratorTrigger[];
98
- }
99
- declare function createContractGenerator(config?: ContractGeneratorConfig): Generator;
100
-
101
- export { type ContractGeneratorConfig as C, type Generator as G, type GeneratorTrigger as a, type GeneratorOptions as b, createContractGenerator as c };
package/dist/index.d.ts DELETED
@@ -1,8 +0,0 @@
1
- export { AppFactory, ServerConfig, createServer, startServer } from './server/index.js';
2
- export { ApiErrorResponse, ApiResponse, ApiSuccessResponse, ErrorResponse } from './types/index.js';
3
- export { H as HttpMethod, I as InferContract, R as RouteContext, a as RouteContract, b as RouteHandler, i as isHttpMethod } from './types-BXibIEyj.js';
4
- import 'hono';
5
- import 'hono/cors';
6
- import '@hono/node-server';
7
- import '@sinclair/typebox';
8
- import 'hono/utils/http-status';