zylaris 1.0.2

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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +558 -0
  3. package/Zylaris.js.png +0 -0
  4. package/examples/default/index.html +13 -0
  5. package/examples/default/package.json +23 -0
  6. package/examples/default/src/app/about/page.tsx +18 -0
  7. package/examples/default/src/app/counter/page.tsx +22 -0
  8. package/examples/default/src/app/global.css +225 -0
  9. package/examples/default/src/app/layout.tsx +33 -0
  10. package/examples/default/src/app/page.tsx +14 -0
  11. package/examples/default/src/entry-client.tsx +87 -0
  12. package/examples/default/src/entry-server.tsx +52 -0
  13. package/examples/default/src/router.ts +60 -0
  14. package/examples/default/tsconfig.json +28 -0
  15. package/examples/default/zylaris.config.ts +24 -0
  16. package/package.json +34 -0
  17. package/packages/adapter/package.json +59 -0
  18. package/packages/adapter/src/adapters/bun.ts +215 -0
  19. package/packages/adapter/src/adapters/cloudflare.ts +278 -0
  20. package/packages/adapter/src/adapters/deno.ts +219 -0
  21. package/packages/adapter/src/adapters/netlify.ts +274 -0
  22. package/packages/adapter/src/adapters/node.ts +155 -0
  23. package/packages/adapter/src/adapters/static.ts +134 -0
  24. package/packages/adapter/src/adapters/vercel.ts +239 -0
  25. package/packages/adapter/src/index.ts +115 -0
  26. package/packages/adapter/src/lib/builder.ts +361 -0
  27. package/packages/adapter/src/types.ts +191 -0
  28. package/packages/adapter/tsconfig.json +8 -0
  29. package/packages/cli/package.json +43 -0
  30. package/packages/cli/src/bin.ts +107 -0
  31. package/packages/cli/src/commands/build.ts +197 -0
  32. package/packages/cli/src/commands/create.ts +222 -0
  33. package/packages/cli/src/commands/deploy.ts +90 -0
  34. package/packages/cli/src/commands/dev.ts +108 -0
  35. package/packages/cli/src/index.ts +6 -0
  36. package/packages/cli/tsconfig.json +9 -0
  37. package/packages/compiler/package.json +39 -0
  38. package/packages/compiler/src/index.ts +210 -0
  39. package/packages/compiler/src/jit.ts +187 -0
  40. package/packages/compiler/tsconfig.json +9 -0
  41. package/packages/core/package.json +55 -0
  42. package/packages/core/src/components.test.ts +125 -0
  43. package/packages/core/src/components.ts +181 -0
  44. package/packages/core/src/config.ts +204 -0
  45. package/packages/core/src/hooks.ts +142 -0
  46. package/packages/core/src/index.ts +59 -0
  47. package/packages/core/src/jsx-runtime.ts +46 -0
  48. package/packages/core/tsconfig.json +16 -0
  49. package/packages/dev-server/package.json +51 -0
  50. package/packages/dev-server/src/index.ts +306 -0
  51. package/packages/dev-server/src/jit-middleware.ts +78 -0
  52. package/packages/dev-server/tsconfig.json +9 -0
  53. package/packages/plugins/package.json +44 -0
  54. package/packages/plugins/src/cdn/loader.ts +275 -0
  55. package/packages/plugins/src/index.ts +238 -0
  56. package/packages/plugins/src/loaders/auto-import.ts +219 -0
  57. package/packages/plugins/src/loaders/external.ts +332 -0
  58. package/packages/plugins/src/transforms/index.ts +407 -0
  59. package/packages/plugins/src/types.ts +296 -0
  60. package/packages/plugins/tsconfig.json +8 -0
  61. package/packages/reactivity/package.json +36 -0
  62. package/packages/reactivity/src/computed.d.ts +3 -0
  63. package/packages/reactivity/src/computed.d.ts.map +1 -0
  64. package/packages/reactivity/src/computed.js +64 -0
  65. package/packages/reactivity/src/computed.js.map +1 -0
  66. package/packages/reactivity/src/computed.test.ts +83 -0
  67. package/packages/reactivity/src/computed.ts +69 -0
  68. package/packages/reactivity/src/index.d.ts +6 -0
  69. package/packages/reactivity/src/index.d.ts.map +1 -0
  70. package/packages/reactivity/src/index.js +7 -0
  71. package/packages/reactivity/src/index.js.map +1 -0
  72. package/packages/reactivity/src/index.ts +18 -0
  73. package/packages/reactivity/src/resource.d.ts +6 -0
  74. package/packages/reactivity/src/resource.d.ts.map +1 -0
  75. package/packages/reactivity/src/resource.js +43 -0
  76. package/packages/reactivity/src/resource.js.map +1 -0
  77. package/packages/reactivity/src/resource.test.ts +70 -0
  78. package/packages/reactivity/src/resource.ts +59 -0
  79. package/packages/reactivity/src/signal.d.ts +7 -0
  80. package/packages/reactivity/src/signal.d.ts.map +1 -0
  81. package/packages/reactivity/src/signal.js +145 -0
  82. package/packages/reactivity/src/signal.js.map +1 -0
  83. package/packages/reactivity/src/signal.test.ts +130 -0
  84. package/packages/reactivity/src/signal.ts +207 -0
  85. package/packages/reactivity/src/store.d.ts +4 -0
  86. package/packages/reactivity/src/store.d.ts.map +1 -0
  87. package/packages/reactivity/src/store.js +62 -0
  88. package/packages/reactivity/src/store.js.map +1 -0
  89. package/packages/reactivity/src/store.test.ts +38 -0
  90. package/packages/reactivity/src/store.ts +111 -0
  91. package/packages/reactivity/src/types.d.ts +43 -0
  92. package/packages/reactivity/src/types.d.ts.map +1 -0
  93. package/packages/reactivity/src/types.js +3 -0
  94. package/packages/reactivity/src/types.js.map +1 -0
  95. package/packages/reactivity/src/types.ts +43 -0
  96. package/packages/reactivity/tsconfig.json +9 -0
  97. package/packages/router/package.json +44 -0
  98. package/packages/router/src/components.tsx +150 -0
  99. package/packages/router/src/fs-router.ts +163 -0
  100. package/packages/router/src/index.ts +22 -0
  101. package/packages/router/src/router.test.ts +111 -0
  102. package/packages/router/src/router.ts +112 -0
  103. package/packages/router/src/types.ts +69 -0
  104. package/packages/router/tsconfig.json +10 -0
  105. package/packages/server/package.json +41 -0
  106. package/packages/server/src/action.test.ts +102 -0
  107. package/packages/server/src/action.ts +201 -0
  108. package/packages/server/src/api.ts +143 -0
  109. package/packages/server/src/index.ts +18 -0
  110. package/packages/server/src/types.ts +72 -0
  111. package/packages/server/tsconfig.json +9 -0
  112. package/pnpm-workspace.yaml +4 -0
  113. package/scripts/publish.ps1 +138 -0
  114. package/scripts/publish.sh +142 -0
  115. package/tsconfig.json +28 -0
  116. package/turbo.json +24 -0
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@zylaris/server",
3
+ "version": "1.0.0",
4
+ "description": "Server-side utilities for Zylaris",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsc --watch",
21
+ "test": "vitest run --passWithNoTests",
22
+ "typecheck": "tsc --noEmit",
23
+ "clean": "rm -rf dist"
24
+ },
25
+ "dependencies": {
26
+ "@zylaris/reactivity": "workspace:*",
27
+ "zod": "^3.22.4"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^20.0.0",
31
+ "typescript": "^5.3.3",
32
+ "vitest": "^1.2.0"
33
+ },
34
+ "keywords": [
35
+ "server",
36
+ "actions",
37
+ "api",
38
+ "zylaris"
39
+ ],
40
+ "license": "MIT"
41
+ }
@@ -0,0 +1,102 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { action, ActionBuilder, Action, requireAuth, requireRole } from './action.js';
3
+ import type { ActionContext } from './types.js';
4
+
5
+ describe('ActionBuilder', () => {
6
+ it('should create action builder', () => {
7
+ const builder = action();
8
+ expect(builder).toBeInstanceOf(ActionBuilder);
9
+ });
10
+
11
+ it('should build action with run', async () => {
12
+ const myAction = action().run(async (input) => {
13
+ const { name } = input as { name: string };
14
+ return { message: `Hello ${name}` };
15
+ });
16
+
17
+ expect(myAction).toBeInstanceOf(Action);
18
+ });
19
+ });
20
+
21
+ describe('Action', () => {
22
+ it('should execute action successfully', async () => {
23
+ const myAction = action().run(async (input) => {
24
+ const { value } = input as { value: number };
25
+ return { result: value * 2 };
26
+ });
27
+
28
+ const result = await myAction.execute({ value: 5 }, {
29
+ request: new Request('http://localhost'),
30
+ headers: new Headers(),
31
+ cookies: new Map(),
32
+ ip: '127.0.0.1',
33
+ userAgent: 'test'
34
+ });
35
+
36
+ expect(result.success).toBe(true);
37
+ expect(result.data).toEqual({ result: 10 });
38
+ });
39
+
40
+ it('should execute with null input', async () => {
41
+ const myAction = action().run(async () => {
42
+ return { success: true };
43
+ });
44
+
45
+ const result = await myAction.execute(null, {
46
+ request: new Request('http://localhost'),
47
+ headers: new Headers(),
48
+ cookies: new Map(),
49
+ ip: '127.0.0.1',
50
+ userAgent: 'test'
51
+ });
52
+
53
+ // Action without input validation should succeed
54
+ expect(result.success).toBe(true);
55
+ });
56
+ });
57
+
58
+ describe('requireAuth', () => {
59
+ it('should return error when no user', async () => {
60
+ const middleware = requireAuth();
61
+ const result = await middleware({
62
+ request: new Request('http://localhost'),
63
+ headers: new Headers(),
64
+ cookies: new Map(),
65
+ ip: '127.0.0.1',
66
+ userAgent: 'test'
67
+ } as ActionContext);
68
+
69
+ expect(result).not.toBeNull();
70
+ expect(result && result.code).toBe('UNAUTHORIZED');
71
+ });
72
+
73
+ it('should return null when user exists', async () => {
74
+ const middleware = requireAuth();
75
+ const result = await middleware({
76
+ request: new Request('http://localhost'),
77
+ headers: new Headers(),
78
+ cookies: new Map(),
79
+ ip: '127.0.0.1',
80
+ userAgent: 'test',
81
+ user: { id: '1', email: 'test@test.com' }
82
+ } as ActionContext);
83
+
84
+ expect(result).toBeNull();
85
+ });
86
+ });
87
+
88
+ describe('requireRole', () => {
89
+ it('should return error when no user', async () => {
90
+ const middleware = requireRole(['admin']);
91
+ const result = await middleware({
92
+ request: new Request('http://localhost'),
93
+ headers: new Headers(),
94
+ cookies: new Map(),
95
+ ip: '127.0.0.1',
96
+ userAgent: 'test'
97
+ } as ActionContext);
98
+
99
+ expect(result).not.toBeNull();
100
+ expect(result && result.code).toBe('UNAUTHORIZED');
101
+ });
102
+ });
@@ -0,0 +1,201 @@
1
+ import type { ZodType } from 'zod';
2
+ import type {
3
+ ActionConfig,
4
+ ActionContext,
5
+ ActionResult,
6
+ ActionError,
7
+ Middleware,
8
+ RateLimitConfig,
9
+ ActionHandler,
10
+ } from './types.js';
11
+
12
+ // Rate limiting store (in production, use Redis)
13
+ const rateLimitStore = new Map<string, { count: number; resetAt: number }>();
14
+
15
+ export class ActionBuilder<I, O> {
16
+ private config: ActionConfig<I, O>;
17
+
18
+ constructor(config: ActionConfig<I, O> = {}) {
19
+ this.config = config;
20
+ }
21
+
22
+ input<T extends ZodType>(schema: T): ActionBuilder<ReturnType<T['parse']>, O> {
23
+ return new ActionBuilder({ ...this.config, input: schema });
24
+ }
25
+
26
+ output<T extends ZodType>(schema: T): ActionBuilder<I, ReturnType<T['parse']>> {
27
+ return new ActionBuilder({ ...this.config, output: schema });
28
+ }
29
+
30
+ use(middleware: Middleware): this {
31
+ this.config.middleware = [...(this.config.middleware || []), middleware];
32
+ return this;
33
+ }
34
+
35
+ rateLimit(config: RateLimitConfig): this {
36
+ this.config.rateLimit = config;
37
+ return this;
38
+ }
39
+
40
+ run(handler: ActionHandler<I, O>): Action<I, O> {
41
+ return new Action(this.config, handler);
42
+ }
43
+ }
44
+
45
+ export class Action<I, O> {
46
+ id: string;
47
+
48
+ constructor(
49
+ private config: ActionConfig<I, O>,
50
+ private handler: ActionHandler<I, O>
51
+ ) {
52
+ this.id = generateActionId();
53
+ }
54
+
55
+ async execute(input: unknown, ctx: ActionContext): Promise<ActionResult<O>> {
56
+ try {
57
+ // Check rate limit
58
+ if (this.config.rateLimit) {
59
+ const rateLimitError = await checkRateLimit(this.config.rateLimit, ctx);
60
+ if (rateLimitError) {
61
+ return { success: false, error: rateLimitError };
62
+ }
63
+ }
64
+
65
+ // Run middleware
66
+ if (this.config.middleware) {
67
+ for (const middleware of this.config.middleware) {
68
+ const result = await middleware(ctx);
69
+ if (result) {
70
+ return { success: false, error: result };
71
+ }
72
+ }
73
+ }
74
+
75
+ // Validate input
76
+ let validatedInput: I;
77
+ if (this.config.input) {
78
+ const result = this.config.input.safeParse(input);
79
+ if (!result.success) {
80
+ return {
81
+ success: false,
82
+ error: {
83
+ code: 'VALIDATION_ERROR',
84
+ message: 'Input validation failed',
85
+ fieldErrors: result.error.flatten().fieldErrors as Record<string, string[]>,
86
+ },
87
+ };
88
+ }
89
+ validatedInput = result.data as I;
90
+ } else {
91
+ validatedInput = input as I;
92
+ }
93
+
94
+ // Execute handler
95
+ const output = await this.handler(validatedInput, ctx);
96
+
97
+ // Validate output
98
+ if (this.config.output) {
99
+ const result = this.config.output.safeParse(output);
100
+ if (!result.success) {
101
+ return {
102
+ success: false,
103
+ error: {
104
+ code: 'OUTPUT_VALIDATION_ERROR',
105
+ message: 'Output validation failed',
106
+ },
107
+ };
108
+ }
109
+ }
110
+
111
+ return { success: true, data: output };
112
+ } catch (error) {
113
+ return {
114
+ success: false,
115
+ error: {
116
+ code: 'INTERNAL_ERROR',
117
+ message: error instanceof Error ? error.message : 'Unknown error',
118
+ },
119
+ };
120
+ }
121
+ }
122
+ }
123
+
124
+ function generateActionId(): string {
125
+ return `action_${Math.random().toString(36).substring(2, 11)}`;
126
+ }
127
+
128
+ async function checkRateLimit(
129
+ config: RateLimitConfig,
130
+ ctx: ActionContext
131
+ ): Promise<ActionError | null> {
132
+ const key = config.key ? config.key(ctx) : ctx.ip;
133
+ const windowMs = parseTimeWindow(config.window);
134
+ const now = Date.now();
135
+
136
+ const record = rateLimitStore.get(key);
137
+
138
+ if (!record || now > record.resetAt) {
139
+ rateLimitStore.set(key, {
140
+ count: 1,
141
+ resetAt: now + windowMs,
142
+ });
143
+ return null;
144
+ }
145
+
146
+ if (record.count >= config.max) {
147
+ return {
148
+ code: 'RATE_LIMIT_EXCEEDED',
149
+ message: `Rate limit exceeded. Try again in ${Math.ceil((record.resetAt - now) / 1000)}s`,
150
+ };
151
+ }
152
+
153
+ record.count++;
154
+ return null;
155
+ }
156
+
157
+ function parseTimeWindow(window: string): number {
158
+ const match = window.match(/^(\d+)([smhd])$/);
159
+ if (!match) return 60000; // Default 1 minute
160
+
161
+ const [, num, unit] = match;
162
+ const multiplier = {
163
+ s: 1000,
164
+ m: 60000,
165
+ h: 3600000,
166
+ d: 86400000,
167
+ }[unit] || 60000;
168
+
169
+ return parseInt(num) * multiplier;
170
+ }
171
+
172
+ // Factory function
173
+ export function action(): ActionBuilder<unknown, unknown> {
174
+ return new ActionBuilder();
175
+ }
176
+
177
+ // Built-in middleware
178
+ export function requireAuth(): Middleware {
179
+ return (ctx) => {
180
+ if (!ctx.user) {
181
+ return {
182
+ code: 'UNAUTHORIZED',
183
+ message: 'Authentication required',
184
+ };
185
+ }
186
+ return null;
187
+ };
188
+ }
189
+
190
+ export function requireRole(_roles: string[]): Middleware {
191
+ return (ctx) => {
192
+ if (!ctx.user) {
193
+ return {
194
+ code: 'UNAUTHORIZED',
195
+ message: 'Authentication required',
196
+ };
197
+ }
198
+ // In real implementation, check user roles
199
+ return null;
200
+ };
201
+ }
@@ -0,0 +1,143 @@
1
+ import type { ZodType } from 'zod';
2
+ import type {
3
+ APIConfig,
4
+ APIHandler,
5
+ ActionContext,
6
+ Middleware,
7
+ } from './types.js';
8
+
9
+ export class APIBuilder<I, O> {
10
+ private config: APIConfig<I, O>;
11
+
12
+ constructor(config: APIConfig<I, O> = {}) {
13
+ this.config = config;
14
+ }
15
+
16
+ query<T extends ZodType>(schema: T): APIBuilder<ReturnType<T['parse']>, O> {
17
+ return new APIBuilder({ ...this.config, query: schema });
18
+ }
19
+
20
+ body<T extends ZodType>(schema: T): APIBuilder<ReturnType<T['parse']>, O> {
21
+ return new APIBuilder({ ...this.config, body: schema });
22
+ }
23
+
24
+ output<T extends ZodType>(schema: T): APIBuilder<I, ReturnType<T['parse']>> {
25
+ return new APIBuilder({ ...this.config, output: schema });
26
+ }
27
+
28
+ use(middleware: Middleware): this {
29
+ this.config.middleware = [...(this.config.middleware || []), middleware];
30
+ return this;
31
+ }
32
+
33
+ handler(fn: APIHandler<I, O>): (request: Request) => Promise<Response> {
34
+ return async (request: Request) => {
35
+ try {
36
+ const ctx = await createContext(request);
37
+
38
+ // Run middleware
39
+ if (this.config.middleware) {
40
+ for (const middleware of this.config.middleware) {
41
+ const result = await middleware(ctx);
42
+ if (result) {
43
+ return Response.json(
44
+ { success: false, error: result },
45
+ { status: 400 }
46
+ );
47
+ }
48
+ }
49
+ }
50
+
51
+ // Parse input
52
+ let input: I = {} as I;
53
+
54
+ if (this.config.query) {
55
+ const url = new URL(request.url);
56
+ const query = Object.fromEntries(url.searchParams);
57
+ const result = this.config.query.safeParse(query);
58
+ if (!result.success) {
59
+ return Response.json(
60
+ {
61
+ success: false,
62
+ error: {
63
+ code: 'VALIDATION_ERROR',
64
+ message: 'Query validation failed',
65
+ fieldErrors: result.error.flatten().fieldErrors,
66
+ },
67
+ },
68
+ { status: 400 }
69
+ );
70
+ }
71
+ input = { ...input, ...result.data };
72
+ }
73
+
74
+ if (this.config.body && request.body) {
75
+ const body = await request.json();
76
+ const result = this.config.body.safeParse(body);
77
+ if (!result.success) {
78
+ return Response.json(
79
+ {
80
+ success: false,
81
+ error: {
82
+ code: 'VALIDATION_ERROR',
83
+ message: 'Body validation failed',
84
+ fieldErrors: result.error.flatten().fieldErrors,
85
+ },
86
+ },
87
+ { status: 400 }
88
+ );
89
+ }
90
+ input = { ...input, ...result.data };
91
+ }
92
+
93
+ // Execute handler
94
+ const response = await fn(input, ctx);
95
+ return response;
96
+ } catch (error) {
97
+ console.error('API Error:', error);
98
+ return Response.json(
99
+ {
100
+ success: false,
101
+ error: {
102
+ code: 'INTERNAL_ERROR',
103
+ message: error instanceof Error ? error.message : 'Unknown error',
104
+ },
105
+ },
106
+ { status: 500 }
107
+ );
108
+ }
109
+ };
110
+ }
111
+ }
112
+
113
+ async function createContext(request: Request): Promise<ActionContext> {
114
+ const headers = request.headers;
115
+ const cookies = parseCookies(headers.get('cookie') || '');
116
+
117
+ return {
118
+ request,
119
+ headers,
120
+ cookies,
121
+ ip: headers.get('x-forwarded-for') || 'unknown',
122
+ userAgent: headers.get('user-agent') || 'unknown',
123
+ };
124
+ }
125
+
126
+ function parseCookies(cookieHeader: string): Map<string, string> {
127
+ const cookies = new Map<string, string>();
128
+ if (!cookieHeader) return cookies;
129
+
130
+ cookieHeader.split(';').forEach((cookie) => {
131
+ const [name, value] = cookie.trim().split('=');
132
+ if (name && value) {
133
+ cookies.set(name, decodeURIComponent(value));
134
+ }
135
+ });
136
+
137
+ return cookies;
138
+ }
139
+
140
+ // Factory function
141
+ export function api(): APIBuilder<unknown, unknown> {
142
+ return new APIBuilder();
143
+ }
@@ -0,0 +1,18 @@
1
+ // Zylaris Server - Server-side utilities
2
+
3
+ export { Action, ActionBuilder, action, requireAuth, requireRole } from './action.js';
4
+ export { APIBuilder, api } from './api.js';
5
+
6
+ export type {
7
+ ActionContext,
8
+ User,
9
+ Session,
10
+ ActionConfig,
11
+ ActionResult,
12
+ ActionError,
13
+ Middleware,
14
+ RateLimitConfig,
15
+ ActionHandler,
16
+ APIConfig,
17
+ APIHandler,
18
+ } from './types.js';
@@ -0,0 +1,72 @@
1
+ import type { ZodType } from 'zod';
2
+
3
+ export interface ActionContext {
4
+ request: Request;
5
+ headers: Headers;
6
+ cookies: Map<string, string>;
7
+ user?: User;
8
+ session?: Session;
9
+ ip: string;
10
+ userAgent: string;
11
+ }
12
+
13
+ export interface User {
14
+ id: string;
15
+ email: string;
16
+ name?: string;
17
+ [key: string]: unknown;
18
+ }
19
+
20
+ export interface Session {
21
+ id: string;
22
+ userId: string;
23
+ expiresAt: Date;
24
+ [key: string]: unknown;
25
+ }
26
+
27
+ export interface ActionConfig<I, O> {
28
+ input?: ZodType<I>;
29
+ output?: ZodType<O>;
30
+ middleware?: Middleware[];
31
+ rateLimit?: RateLimitConfig;
32
+ }
33
+
34
+ export interface ActionResult<O> {
35
+ success: boolean;
36
+ data?: O;
37
+ error?: ActionError;
38
+ }
39
+
40
+ export interface ActionError {
41
+ code: string;
42
+ message: string;
43
+ fieldErrors?: Record<string, string[]>;
44
+ }
45
+
46
+ export type Middleware = (
47
+ ctx: ActionContext
48
+ ) => Promise<ActionError | null | undefined> | ActionError | null | undefined;
49
+
50
+ export interface RateLimitConfig {
51
+ max: number;
52
+ window: string; // e.g., '1m', '1h'
53
+ key?: (ctx: ActionContext) => string;
54
+ }
55
+
56
+ export type ActionHandler<I, O> = (
57
+ input: I,
58
+ ctx: ActionContext
59
+ ) => Promise<O> | O;
60
+
61
+ // API Route types
62
+ export interface APIConfig<I, O> {
63
+ query?: ZodType<I>;
64
+ body?: ZodType<I>;
65
+ output?: ZodType<O>;
66
+ middleware?: Middleware[];
67
+ }
68
+
69
+ export type APIHandler<_I, _O> = (
70
+ input: _I,
71
+ ctx: ActionContext
72
+ ) => Promise<Response> | Response;
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["dist", "node_modules"]
9
+ }
@@ -0,0 +1,4 @@
1
+ packages:
2
+ - 'packages/*'
3
+ - 'templates/*'
4
+ - 'examples/*'