@tamayrp14/fire-api 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +276 -2
  2. package/bin/fire.js +139 -0
  3. package/bun.lock +20 -0
  4. package/docs/GETTING_STARTED.md +150 -0
  5. package/docs/LAUNCH_KIT.md +236 -0
  6. package/docs/superpowers/plans/2026-11-14-fire-api-framework.md +144 -0
  7. package/docs/superpowers/specs/fire-api-design-spec.md +111 -0
  8. package/examples/basic-api/index.ts +177 -0
  9. package/package.json +68 -4
  10. package/src/ai/mcp.ts +140 -0
  11. package/src/auth/auth.ts +110 -0
  12. package/src/auth/crypto.ts +70 -0
  13. package/src/auth/jwt.ts +105 -0
  14. package/src/cache/cache.ts +72 -0
  15. package/src/cli/bench.ts +118 -0
  16. package/src/cli/compile.ts +29 -0
  17. package/src/cli/create-app.ts +284 -0
  18. package/src/cli/docker.ts +51 -0
  19. package/src/cli/generator.ts +75 -0
  20. package/src/cli/routes.ts +76 -0
  21. package/src/client.ts +120 -0
  22. package/src/compat/express.ts +139 -0
  23. package/src/core/app.ts +723 -0
  24. package/src/core/context.ts +218 -0
  25. package/src/core/error.ts +42 -0
  26. package/src/core/router.ts +262 -0
  27. package/src/db/db-interface.ts +9 -0
  28. package/src/db/hub.ts +256 -0
  29. package/src/db/memory-adapter.ts +202 -0
  30. package/src/db/migrator.ts +100 -0
  31. package/src/db/sqlite-adapter.ts +58 -0
  32. package/src/docs/collection.ts +57 -0
  33. package/src/docs/scalar-ui.ts +25 -0
  34. package/src/events/event-bus.ts +61 -0
  35. package/src/index.ts +37 -0
  36. package/src/jobs/cron.ts +77 -0
  37. package/src/jobs/queue.ts +108 -0
  38. package/src/logging/logger.ts +66 -0
  39. package/src/metrics/metrics.ts +66 -0
  40. package/src/modules/product/product.route.ts +36 -0
  41. package/src/modules/product/product.schema.ts +10 -0
  42. package/src/schema/mock.ts +60 -0
  43. package/src/schema/openapi.ts +101 -0
  44. package/src/schema/schema.ts +519 -0
  45. package/src/schema/validator.ts +5 -0
  46. package/src/shield/compress.ts +61 -0
  47. package/src/shield/cors.ts +94 -0
  48. package/src/shield/headers.ts +55 -0
  49. package/src/shield/idempotency.ts +76 -0
  50. package/src/shield/rate-limiter.ts +81 -0
  51. package/src/shield/sanitizer.ts +23 -0
  52. package/src/shield/webhook.ts +101 -0
  53. package/src/static/serve.ts +51 -0
  54. package/src/storage/storage.ts +176 -0
  55. package/src/stream/sse.ts +89 -0
  56. package/src/studio/studio.ts +221 -0
  57. package/src/types.ts +241 -0
  58. package/src/ws/ws.ts +118 -0
  59. package/test/ai-mcp.test.ts +61 -0
  60. package/test/auth.test.ts +108 -0
  61. package/test/bench.test.ts +31 -0
  62. package/test/cache.test.ts +36 -0
  63. package/test/cli-create.test.ts +64 -0
  64. package/test/client.test.ts +54 -0
  65. package/test/collection-export.test.ts +52 -0
  66. package/test/compat.test.ts +48 -0
  67. package/test/compress.test.ts +48 -0
  68. package/test/context.test.ts +48 -0
  69. package/test/db.test.ts +62 -0
  70. package/test/docker.test.ts +28 -0
  71. package/test/events.test.ts +62 -0
  72. package/test/file-upload.test.ts +116 -0
  73. package/test/hooks.test.ts +77 -0
  74. package/test/idempotency.test.ts +65 -0
  75. package/test/integration.test.ts +111 -0
  76. package/test/jobs.test.ts +60 -0
  77. package/test/metrics.test.ts +40 -0
  78. package/test/mock.test.ts +33 -0
  79. package/test/multi-tenant.test.ts +80 -0
  80. package/test/observability.test.ts +95 -0
  81. package/test/openapi.test.ts +41 -0
  82. package/test/orm-relations.test.ts +85 -0
  83. package/test/orm-shortcuts.test.ts +52 -0
  84. package/test/rbac.test.ts +85 -0
  85. package/test/router-fastpath.test.ts +42 -0
  86. package/test/router.test.ts +84 -0
  87. package/test/schema.test.ts +49 -0
  88. package/test/seeder-migrator.test.ts +78 -0
  89. package/test/shield.test.ts +55 -0
  90. package/test/shorthand-dx.test.ts +31 -0
  91. package/test/sse.test.ts +43 -0
  92. package/test/static-serve.test.ts +53 -0
  93. package/test/storage.test.ts +31 -0
  94. package/test/studio.test.ts +43 -0
  95. package/test/tx.test.ts +92 -0
  96. package/test/webhook.test.ts +113 -0
  97. package/test/ws.test.ts +54 -0
  98. package/tsconfig.json +19 -0
@@ -0,0 +1,139 @@
1
+ import { Middleware } from '../types';
2
+
3
+ export type ExpressMiddleware = (
4
+ req: any,
5
+ res: any,
6
+ next: (err?: any) => void
7
+ ) => void | Promise<void>;
8
+
9
+ export function fromExpress(expressMiddleware: ExpressMiddleware): Middleware {
10
+ return async (ctx, next) => {
11
+ let statusCode = 200;
12
+ const responseHeaders = new Headers();
13
+ let earlyResponse: Response | null = null;
14
+ let nextCalled = false;
15
+
16
+ // Use a clean proxy to avoid assigning to readonly properties on native Request
17
+ const customProps: Record<string, any> = {
18
+ url: new URL(ctx.req.url).pathname,
19
+ path: new URL(ctx.req.url).pathname,
20
+ method: ctx.req.method,
21
+ headers: Object.fromEntries(ctx.req.headers.entries()),
22
+ params: ctx.params,
23
+ query: ctx.query,
24
+ body: ctx.body,
25
+ };
26
+
27
+ const simulatedReq = new Proxy(ctx.req, {
28
+ get(target, prop: string) {
29
+ if (prop in customProps) {
30
+ return customProps[prop];
31
+ }
32
+ const val = (target as any)[prop];
33
+ return typeof val === 'function' ? val.bind(target) : val;
34
+ },
35
+ set(_target, prop: string, value: any) {
36
+ customProps[prop] = value;
37
+ return true;
38
+ },
39
+ has(_target, prop: string) {
40
+ return prop in customProps || prop in _target;
41
+ },
42
+ });
43
+
44
+ // Point ctx.req to proxy so handlers have access to properties attached by Express middleware
45
+ (ctx as any).req = simulatedReq;
46
+
47
+ // Simulated Express res
48
+ const simulatedRes: any = {
49
+ statusCode: 200,
50
+ setHeader(name: string, value: string) {
51
+ responseHeaders.set(name, value);
52
+ return this;
53
+ },
54
+ getHeader(name: string) {
55
+ return responseHeaders.get(name);
56
+ },
57
+ removeHeader(name: string) {
58
+ responseHeaders.delete(name);
59
+ return this;
60
+ },
61
+ status(code: number) {
62
+ statusCode = code;
63
+ this.statusCode = code;
64
+ return this;
65
+ },
66
+ json(data: any) {
67
+ responseHeaders.set('Content-Type', 'application/json');
68
+ earlyResponse = new Response(JSON.stringify(data), {
69
+ status: statusCode,
70
+ headers: responseHeaders,
71
+ });
72
+ return this;
73
+ },
74
+ send(body: any) {
75
+ if (typeof body === 'object' && body !== null) {
76
+ return this.json(body);
77
+ }
78
+ if (!responseHeaders.has('Content-Type')) {
79
+ responseHeaders.set('Content-Type', 'text/html; charset=utf-8');
80
+ }
81
+ earlyResponse = new Response(String(body ?? ''), {
82
+ status: statusCode,
83
+ headers: responseHeaders,
84
+ });
85
+ return this;
86
+ },
87
+ end(chunk?: any) {
88
+ if (chunk) {
89
+ return this.send(chunk);
90
+ }
91
+ earlyResponse = new Response(null, {
92
+ status: statusCode,
93
+ headers: responseHeaders,
94
+ });
95
+ return this;
96
+ },
97
+ };
98
+
99
+ return new Promise<Response>((resolve, reject) => {
100
+ try {
101
+ const nextFn = async (err?: any) => {
102
+ nextCalled = true;
103
+ if (err) {
104
+ reject(err);
105
+ return;
106
+ }
107
+ try {
108
+ const downstreamResponse = await next();
109
+ const mergedHeaders = new Headers(downstreamResponse.headers);
110
+ responseHeaders.forEach((v, k) => mergedHeaders.set(k, v));
111
+
112
+ resolve(
113
+ new Response(downstreamResponse.body, {
114
+ status: downstreamResponse.status,
115
+ statusText: downstreamResponse.statusText,
116
+ headers: mergedHeaders,
117
+ })
118
+ );
119
+ } catch (e) {
120
+ reject(e);
121
+ }
122
+ };
123
+
124
+ const result = expressMiddleware(simulatedReq, simulatedRes, nextFn);
125
+
126
+ if (result && typeof (result as any).catch === 'function') {
127
+ (result as any).catch(reject);
128
+ }
129
+
130
+ // Check if response was sent synchronously without calling next()
131
+ if (!nextCalled && earlyResponse) {
132
+ resolve(earlyResponse);
133
+ }
134
+ } catch (err) {
135
+ reject(err);
136
+ }
137
+ });
138
+ };
139
+ }