@fragno-dev/create 0.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.
- package/.turbo/turbo-build.log +12 -0
- package/.turbo/turbo-test.log +66 -0
- package/.turbo/turbo-types$colon$check.log +1 -0
- package/CHANGELOG.md +7 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +154 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
- package/src/index.ts +84 -0
- package/src/integration.test.ts +97 -0
- package/src/package-json.ts +67 -0
- package/src/utils.test.ts +9 -0
- package/src/utils.ts +69 -0
- package/templates/fragment/AGENTS.md +220 -0
- package/templates/fragment/README.md +16 -0
- package/templates/fragment/package.template.json +65 -0
- package/templates/fragment/src/client/react.ts +7 -0
- package/templates/fragment/src/client/svelte.ts +7 -0
- package/templates/fragment/src/client/vanilla.ts +7 -0
- package/templates/fragment/src/client/vue.ts +7 -0
- package/templates/fragment/src/index.ts +94 -0
- package/templates/fragment/tsconfig.base.json +34 -0
- package/templates/fragment/tsconfig.json +10 -0
- package/templates/optional/builder/esbuild.config.js +34 -0
- package/templates/optional/builder/rollup.config.js +58 -0
- package/templates/optional/builder/rspack.config.js +93 -0
- package/templates/optional/builder/tsdown.config.ts +30 -0
- package/templates/optional/builder/vite.config.ts +25 -0
- package/templates/optional/builder/webpack.config.js +79 -0
- package/tsconfig.json +10 -0
- package/tsdown.config.ts +10 -0
- package/vitest.config.ts +4 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance for AI agents working with Fragno fragments. It contains architectural
|
|
4
|
+
information, development strategies, and practical approaches for building fragments.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
A **Fragment** is a full-stack, framework-agnostic TypeScript library built with Fragno. Fragments
|
|
9
|
+
provide:
|
|
10
|
+
|
|
11
|
+
- Type-safe server-side API routes
|
|
12
|
+
- Automatic client-side hooks/composables for multiple frameworks (React, Vue, Svelte, Vanilla JS)
|
|
13
|
+
- Automatic code splitting between client and server bundles
|
|
14
|
+
- Built-in state management with reactive stores (TanStack Query-style:
|
|
15
|
+
`const {data, loading, error} = useData()`)
|
|
16
|
+
|
|
17
|
+
**Documentation**: Full documentation is available at https://fragno.dev/docs
|
|
18
|
+
|
|
19
|
+
## Architecture
|
|
20
|
+
|
|
21
|
+
Fragments follow a core pattern:
|
|
22
|
+
|
|
23
|
+
1. **Server-side**: Define routes with input/output schemas, handlers, and dependencies
|
|
24
|
+
2. **Client-side**: Auto-generated type-safe hooks for each route
|
|
25
|
+
3. **Code splitting**: Server-only code (handlers, dependencies) is stripped from client bundles
|
|
26
|
+
|
|
27
|
+
## File Structure & Core Concepts
|
|
28
|
+
|
|
29
|
+
### `src/index.ts` - Main Fragment Definition
|
|
30
|
+
|
|
31
|
+
This is the core file that contains the fragment definition, routes, dependencies, services, and
|
|
32
|
+
client builder.
|
|
33
|
+
|
|
34
|
+
**Key concepts defined in this file**:
|
|
35
|
+
|
|
36
|
+
**Fragment Definition** (`defineFragment`):
|
|
37
|
+
|
|
38
|
+
- Takes a config type parameter that defines what users must provide (API keys, callbacks, etc.)
|
|
39
|
+
- The fragment name is used in the URL path: `/api/<fragment-name>/...`
|
|
40
|
+
|
|
41
|
+
**Dependencies** (`.withDependencies()`):
|
|
42
|
+
|
|
43
|
+
- Server-side only (never included in client bundle)
|
|
44
|
+
- Private to the fragment, not accessible to users
|
|
45
|
+
- Access to config for initialization (e.g., API keys, database connections)
|
|
46
|
+
- Used in route handlers
|
|
47
|
+
|
|
48
|
+
**Services** (`.withServices()`):
|
|
49
|
+
|
|
50
|
+
- Server-side only (never included in client bundle)
|
|
51
|
+
- Public-facing API accessible to users via `fragment.services.methodName()`
|
|
52
|
+
- Access to both config and dependencies
|
|
53
|
+
- Useful for exposing utility methods to users
|
|
54
|
+
|
|
55
|
+
**Route Definition** (`defineRoute` and `defineRoutes`):
|
|
56
|
+
|
|
57
|
+
- `defineRoute`: Simple routes without dependencies
|
|
58
|
+
- `defineRoutes`: Route factory that has access to dependencies and services
|
|
59
|
+
- Route handler context:
|
|
60
|
+
- First parameter (input): `{ input, query, pathParams, request, url }`
|
|
61
|
+
- Second parameter (output): `{ json, jsonStream, empty, error }`
|
|
62
|
+
- `input.valid()` validates and returns parsed data (throws on validation error)
|
|
63
|
+
|
|
64
|
+
**Server-Side Fragment** (`createFragment`):
|
|
65
|
+
|
|
66
|
+
- Users call this function to instantiate the fragment on the server
|
|
67
|
+
- Returns an object with request handlers (`handler(request: Request) => Response`) and `services`
|
|
68
|
+
|
|
69
|
+
**Client-Side Builder** (`createClientBuilder`):
|
|
70
|
+
|
|
71
|
+
- Creates type-safe hooks for each route
|
|
72
|
+
- `createHook(path)`: For GET routes (returns `{ data, loading, error }`)
|
|
73
|
+
- `createMutator(method, path)`: For POST/PUT/PATCH/DELETE routes (returns
|
|
74
|
+
`{ data, loading, error, mutate }`)
|
|
75
|
+
- Advanced: Use `computed`, `atom` from `nanostores` for derived state
|
|
76
|
+
|
|
77
|
+
### `src/client/*.ts` - Framework-Specific Exports
|
|
78
|
+
|
|
79
|
+
Each framework requires a separate client file that wraps the generic client builder with the
|
|
80
|
+
framework-specific `useFragno` hook. Check the `src/client/` directory for existing framework
|
|
81
|
+
implementations. Use the frameworks page on https://fragno.dev/docs/frameworks to see if all clients
|
|
82
|
+
have their stubs defined. Make sure to include new frameworks in the exports section of
|
|
83
|
+
package.json.
|
|
84
|
+
|
|
85
|
+
### `package.json` - Package Configuration
|
|
86
|
+
|
|
87
|
+
The package.json defines multiple export paths for different frameworks and environments. Key
|
|
88
|
+
points:
|
|
89
|
+
|
|
90
|
+
- Main export (`.`) is server-side code
|
|
91
|
+
- Framework exports (`./react`, `./vue`, `./svelte`, `./vanilla`) use "browser" condition to load
|
|
92
|
+
client bundle
|
|
93
|
+
- Development mode uses source files for better debugging
|
|
94
|
+
- Production uses built files from `dist/`
|
|
95
|
+
- When adding new framework exports, add corresponding client files in `src/client/`
|
|
96
|
+
|
|
97
|
+
## Strategies for Building Fragments
|
|
98
|
+
|
|
99
|
+
### OpenAPI/Swagger Spec → Fragno Routes
|
|
100
|
+
|
|
101
|
+
Parse an OpenAPI specification and convert it to Fragno routes. Map HTTP methods to `defineRoute`,
|
|
102
|
+
convert path parameters (e.g., `/users/{id}` → `/users/:id`), convert JSON schemas to Zod schemas
|
|
103
|
+
for `inputSchema`/`outputSchema`, and generate handlers. Group related routes using `defineRoutes`
|
|
104
|
+
if they share dependencies. Extract error codes from OpenAPI error responses.
|
|
105
|
+
|
|
106
|
+
### REST API Wrapper
|
|
107
|
+
|
|
108
|
+
Wrap an existing REST API with proper typing and error handling. Add HTTP client (fetch, axios) to
|
|
109
|
+
dependencies with API credentials from config. Create routes that proxy to API endpoints with proper
|
|
110
|
+
error handling and validation. Optionally add caching or rate limiting in services. This approach is
|
|
111
|
+
useful when you want to provide a type-safe interface to an existing API.
|
|
112
|
+
|
|
113
|
+
### Third-Party SDK Integration
|
|
114
|
+
|
|
115
|
+
Wrap third-party SDKs (Stripe, OpenAI, Twilio, etc.) as fragments. Add SDK to dependencies with API
|
|
116
|
+
keys from config. Create routes that expose SDK functionality, transform SDK responses to match your
|
|
117
|
+
schemas, and handle SDK-specific errors and rate limits. Optionally expose the SDK client directly
|
|
118
|
+
in services for advanced users. Use streaming responses for real-time SDK features like AI chat.
|
|
119
|
+
|
|
120
|
+
## Development Workflow
|
|
121
|
+
|
|
122
|
+
### Building
|
|
123
|
+
|
|
124
|
+
Fragments require code splitting between client and server bundles using
|
|
125
|
+
`@fragno-dev/unplugin-fragno`. The plugin can also be imported for different kinds of build tools:
|
|
126
|
+
`/esbuild`, `/rollup`, `/webpack`, `/rspack`, `/farm`.
|
|
127
|
+
|
|
128
|
+
### Type Checking
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
bun run types:check
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Common Patterns
|
|
135
|
+
|
|
136
|
+
### Streaming Responses
|
|
137
|
+
|
|
138
|
+
For real-time data (e.g., AI chat, large datasets), use `jsonStream` with `stream.write()` and
|
|
139
|
+
`stream.sleep()`. The output schema must be an array. Client-side: The `data` array is updated
|
|
140
|
+
reactively as chunks arrive.
|
|
141
|
+
|
|
142
|
+
### Error Handling
|
|
143
|
+
|
|
144
|
+
- Always define `errorCodes` array in route definition
|
|
145
|
+
- Use structured errors: `error({ message: string, code: string }, statusCode)`
|
|
146
|
+
- `input.valid()` automatically throws validation errors (converted to 400 responses)
|
|
147
|
+
- Check for null/undefined before processing and return appropriate error codes
|
|
148
|
+
|
|
149
|
+
### Create Callbacks
|
|
150
|
+
|
|
151
|
+
Allow users to react to events by including optional callback functions in your config:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
interface FragmentConfig {
|
|
155
|
+
onDataCreated?: (data: Data) => void;
|
|
156
|
+
onError?: (error: Error) => void;
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Call them in handlers after operations complete: `config.onDataCreated?.(data);`
|
|
161
|
+
|
|
162
|
+
## Using Your Fragment in Other Projects
|
|
163
|
+
|
|
164
|
+
Once you've built and published your fragment, users can integrate it into their projects. The
|
|
165
|
+
integration has two parts:
|
|
166
|
+
|
|
167
|
+
### 1. Server-Side Setup
|
|
168
|
+
|
|
169
|
+
Create a server instance of your fragment (e.g., in `lib/fragment-server.ts`):
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import { createFragment } from "your-fragment-name";
|
|
173
|
+
|
|
174
|
+
export const createFragmentInstance = () =>
|
|
175
|
+
createFragment({
|
|
176
|
+
// Fragment-specific configuration here
|
|
177
|
+
apiKey: process.env.API_KEY,
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Then mount it as a route handler. For example, in Next.js:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// app/api/your-fragment/[...all]/route.ts
|
|
185
|
+
import { createFragmentInstance } from "@/lib/fragment-server";
|
|
186
|
+
|
|
187
|
+
const fragment = createFragmentInstance();
|
|
188
|
+
export const { GET, POST, PUT, PATCH, DELETE } = fragment.handlersFor("next-js");
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 2. Client-Side Setup
|
|
192
|
+
|
|
193
|
+
Initialize the client in your app (e.g., React):
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// lib/fragment-client.ts
|
|
197
|
+
import { createFragmentClient } from "your-fragment-name/react";
|
|
198
|
+
|
|
199
|
+
export const { useData, useMutateData } = createFragmentClient({
|
|
200
|
+
// Optional Fragno configuration
|
|
201
|
+
baseUrl: "/",
|
|
202
|
+
mountRoute: "/api/your-fragment",
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Then use the generated hooks in your components:
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import { useData } from "@/lib/fragment-client";
|
|
210
|
+
|
|
211
|
+
function MyComponent() {
|
|
212
|
+
const { data, loading, error } = useData({
|
|
213
|
+
/* input */
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
if (loading) return <div>Loading...</div>;
|
|
217
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
218
|
+
return <div>{JSON.stringify(data)}</div>;
|
|
219
|
+
}
|
|
220
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Fragno Fragment
|
|
2
|
+
|
|
3
|
+
You've created a new [Fragno](https://fragno.dev/) fragment!
|
|
4
|
+
|
|
5
|
+
## Build
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run types:check
|
|
9
|
+
npm run build
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Next Steps
|
|
13
|
+
|
|
14
|
+
- Define your routes in `src/index.ts`
|
|
15
|
+
- Add framework-specific clients in `src/client/`
|
|
16
|
+
- See `AGENTS.md` for detailed development patterns
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "A Fragno fragment",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"files": ["dist"],
|
|
5
|
+
"keywords": ["fragno", "typescript", "react", "vue", "svelte"],
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/node/index.d.ts",
|
|
9
|
+
"default": "./dist/node/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./react": {
|
|
12
|
+
"development": {
|
|
13
|
+
"browser": "./dist/browser/client/react.js",
|
|
14
|
+
"default": "./src/client/react.ts"
|
|
15
|
+
},
|
|
16
|
+
"types": "./dist/browser/client/react.d.ts",
|
|
17
|
+
"default": "./dist/browser/client/react.js"
|
|
18
|
+
},
|
|
19
|
+
"./vue": {
|
|
20
|
+
"development": {
|
|
21
|
+
"browser": "./dist/browser/client/vue.js",
|
|
22
|
+
"default": "./src/client/vue.ts"
|
|
23
|
+
},
|
|
24
|
+
"types": "./dist/browser/client/vue.d.ts",
|
|
25
|
+
"default": "./dist/browser/client/vue.js"
|
|
26
|
+
},
|
|
27
|
+
"./svelte": {
|
|
28
|
+
"development": {
|
|
29
|
+
"browser": "./dist/browser/client/svelte.js",
|
|
30
|
+
"default": "./src/client/svelte.ts"
|
|
31
|
+
},
|
|
32
|
+
"types": "./dist/browser/client/svelte.d.ts",
|
|
33
|
+
"default": "./dist/browser/client/svelte.js"
|
|
34
|
+
},
|
|
35
|
+
"./vanilla": {
|
|
36
|
+
"development": {
|
|
37
|
+
"browser": "./dist/browser/client/vanilla.js",
|
|
38
|
+
"default": "./src/client/vanilla.ts"
|
|
39
|
+
},
|
|
40
|
+
"types": "./dist/browser/client/vanilla.d.ts",
|
|
41
|
+
"default": "./dist/browser/client/vanilla.js"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"main": "./dist/node/index.js",
|
|
45
|
+
"module": "./dist/node/index.js",
|
|
46
|
+
"types": "./dist/node/index.d.ts",
|
|
47
|
+
"scripts": {
|
|
48
|
+
"types:check": "tsc --noEmit"
|
|
49
|
+
},
|
|
50
|
+
"type": "module",
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@fragno-dev/core": "^0.0.6",
|
|
53
|
+
"zod": "^4.0.5"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^20"
|
|
57
|
+
},
|
|
58
|
+
"private": true,
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"typescript": "^5",
|
|
61
|
+
"react": ">=18.0.0",
|
|
62
|
+
"svelte": ">=4.0.0",
|
|
63
|
+
"vue": ">=3.0.0"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { useFragno } from "@fragno-dev/core/react";
|
|
2
|
+
import { createExampleFragmentClients } from "..";
|
|
3
|
+
import type { FragnoPublicClientConfig } from "@fragno-dev/core";
|
|
4
|
+
|
|
5
|
+
export function createExampleFragmentClient(config: FragnoPublicClientConfig = {}) {
|
|
6
|
+
return useFragno(createExampleFragmentClients(config));
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { useFragno } from "@fragno-dev/core/svelte";
|
|
2
|
+
import { createExampleFragmentClients } from "..";
|
|
3
|
+
import type { FragnoPublicClientConfig } from "@fragno-dev/core";
|
|
4
|
+
|
|
5
|
+
export function createExampleFragmentClient(config: FragnoPublicClientConfig = {}) {
|
|
6
|
+
return useFragno(createExampleFragmentClients(config));
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { useFragno } from "@fragno-dev/core/vanilla";
|
|
2
|
+
import { createExampleFragmentClients } from "..";
|
|
3
|
+
import type { FragnoPublicClientConfig } from "@fragno-dev/core";
|
|
4
|
+
|
|
5
|
+
export function createExampleFragmentClient(config: FragnoPublicClientConfig = {}) {
|
|
6
|
+
return useFragno(createExampleFragmentClients(config));
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { useFragno } from "@fragno-dev/core/vue";
|
|
2
|
+
import { createExampleFragmentClients } from "..";
|
|
3
|
+
import type { FragnoPublicClientConfig } from "@fragno-dev/core";
|
|
4
|
+
|
|
5
|
+
export function createExampleFragmentClient(config: FragnoPublicClientConfig = {}) {
|
|
6
|
+
return useFragno(createExampleFragmentClients(config));
|
|
7
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineFragment,
|
|
3
|
+
defineRoute,
|
|
4
|
+
defineRoutes,
|
|
5
|
+
createFragment,
|
|
6
|
+
type FragnoPublicClientConfig,
|
|
7
|
+
type FragnoPublicConfig,
|
|
8
|
+
} from "@fragno-dev/core";
|
|
9
|
+
import { createClientBuilder } from "@fragno-dev/core/client";
|
|
10
|
+
|
|
11
|
+
// NOTE: We use zod here for defining schemas, but any StandardSchema library can be used!
|
|
12
|
+
// For a complete list see:
|
|
13
|
+
// https://github.com/standard-schema/standard-schema#what-schema-libraries-implement-the-spec
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
|
|
16
|
+
export interface ExampleFragmentServerConfig {
|
|
17
|
+
initialData?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type ExampleRouteConfig = {
|
|
21
|
+
initialData: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type ExampleRouteDeps = {
|
|
25
|
+
serverSideData: { value: string };
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const exampleRoutesFactory = defineRoutes<ExampleRouteConfig, ExampleRouteDeps>().create(
|
|
29
|
+
({ deps }) => {
|
|
30
|
+
const { serverSideData } = deps;
|
|
31
|
+
|
|
32
|
+
return [
|
|
33
|
+
defineRoute({
|
|
34
|
+
method: "GET",
|
|
35
|
+
path: "/hello",
|
|
36
|
+
outputSchema: z.string(),
|
|
37
|
+
handler: async (_, { json }) => {
|
|
38
|
+
return json(serverSideData.value);
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
|
|
42
|
+
defineRoute({
|
|
43
|
+
method: "POST",
|
|
44
|
+
path: "/hello",
|
|
45
|
+
inputSchema: z.object({ message: z.string() }),
|
|
46
|
+
outputSchema: z.string(),
|
|
47
|
+
errorCodes: [],
|
|
48
|
+
handler: async ({ input }, { json }) => {
|
|
49
|
+
const { message } = await input.valid();
|
|
50
|
+
serverSideData.value = message;
|
|
51
|
+
return json(message);
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
];
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const exampleFragmentDefinition = defineFragment<ExampleFragmentServerConfig>("example-fragment")
|
|
59
|
+
.withDependencies((config: ExampleFragmentServerConfig) => {
|
|
60
|
+
return {
|
|
61
|
+
serverSideData: { value: config.initialData ?? "Hello World! This is a server-side data." },
|
|
62
|
+
};
|
|
63
|
+
})
|
|
64
|
+
.withServices((_cfg, deps) => {
|
|
65
|
+
return {
|
|
66
|
+
getData: () => deps.serverSideData.value,
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export function createExampleFragment(
|
|
71
|
+
serverConfig: ExampleFragmentServerConfig = {},
|
|
72
|
+
fragnoConfig: FragnoPublicConfig = {},
|
|
73
|
+
) {
|
|
74
|
+
const config: ExampleRouteConfig = {
|
|
75
|
+
initialData: serverConfig.initialData ?? "Hello World! This is a server-side data.",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return createFragment(
|
|
79
|
+
exampleFragmentDefinition,
|
|
80
|
+
{ ...serverConfig, ...config },
|
|
81
|
+
[exampleRoutesFactory],
|
|
82
|
+
fragnoConfig,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function createExampleFragmentClients(fragnoConfig: FragnoPublicClientConfig) {
|
|
87
|
+
const b = createClientBuilder(exampleFragmentDefinition, fragnoConfig, [exampleRoutesFactory]);
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
useHello: b.createHook("/hello"),
|
|
91
|
+
useHelloMutator: b.createMutator("POST", "/hello"),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export type { FragnoRouteConfig } from "@fragno-dev/core/api";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Enable latest features
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleDetection": "force",
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"allowJs": false,
|
|
9
|
+
// Bundler mode
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"verbatimModuleSyntax": true,
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
// Project reference specific settings
|
|
14
|
+
"composite": true,
|
|
15
|
+
"declaration": true,
|
|
16
|
+
"declarationMap": true,
|
|
17
|
+
"sourceMap": true,
|
|
18
|
+
"rewriteRelativeImportExtensions": true,
|
|
19
|
+
"emitDeclarationOnly": false,
|
|
20
|
+
"isolatedDeclarations": false,
|
|
21
|
+
"isolatedModules": true,
|
|
22
|
+
// Best practices
|
|
23
|
+
"strict": true,
|
|
24
|
+
"skipLibCheck": true,
|
|
25
|
+
"noFallthroughCasesInSwitch": true,
|
|
26
|
+
"noImplicitReturns": true,
|
|
27
|
+
// Some stricter flags
|
|
28
|
+
"noUnusedParameters": true,
|
|
29
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
30
|
+
// Misc
|
|
31
|
+
"esModuleInterop": true,
|
|
32
|
+
"noErrorTruncation": true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { build } from "esbuild";
|
|
3
|
+
import unpluginFragno from "@fragno-dev/unplugin-fragno/esbuild";
|
|
4
|
+
|
|
5
|
+
build({
|
|
6
|
+
entryPoints: [
|
|
7
|
+
"./src/index.ts",
|
|
8
|
+
"./src/client/react.ts",
|
|
9
|
+
"./src/client/svelte.ts",
|
|
10
|
+
"./src/client/vanilla.ts",
|
|
11
|
+
"./src/client/vue.ts",
|
|
12
|
+
],
|
|
13
|
+
outdir: "./dist/browser",
|
|
14
|
+
bundle: true,
|
|
15
|
+
format: "esm",
|
|
16
|
+
platform: "browser",
|
|
17
|
+
target: "es2020",
|
|
18
|
+
splitting: true,
|
|
19
|
+
sourcemap: true,
|
|
20
|
+
plugins: [unpluginFragno({ platform: "browser" })],
|
|
21
|
+
external: ["react", "svelte", "vue", "zod"],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
build({
|
|
25
|
+
entryPoints: ["./src/index.ts"],
|
|
26
|
+
outdir: "./dist/node",
|
|
27
|
+
bundle: true,
|
|
28
|
+
format: "esm",
|
|
29
|
+
platform: "node",
|
|
30
|
+
target: "node18",
|
|
31
|
+
sourcemap: true,
|
|
32
|
+
plugins: [unpluginFragno({ platform: "node" })],
|
|
33
|
+
external: ["zod"],
|
|
34
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import typescript from "@rollup/plugin-typescript";
|
|
2
|
+
import unpluginFragno from "@fragno-dev/unplugin-fragno/rollup";
|
|
3
|
+
import resolve from "@rollup/plugin-node-resolve";
|
|
4
|
+
|
|
5
|
+
export default [
|
|
6
|
+
// Browser build
|
|
7
|
+
{
|
|
8
|
+
input: {
|
|
9
|
+
index: "./src/index.ts",
|
|
10
|
+
"client/react": "./src/client/react.ts",
|
|
11
|
+
"client/svelte": "./src/client/svelte.ts",
|
|
12
|
+
"client/vanilla": "./src/client/vanilla.ts",
|
|
13
|
+
"client/vue": "./src/client/vue.ts",
|
|
14
|
+
},
|
|
15
|
+
output: {
|
|
16
|
+
dir: "./dist/browser",
|
|
17
|
+
format: "es",
|
|
18
|
+
sourcemap: true,
|
|
19
|
+
},
|
|
20
|
+
// https://rollupjs.org/tools/#peer-dependencies
|
|
21
|
+
external: ["zod", "react", "svelte", "vue"],
|
|
22
|
+
plugins: [
|
|
23
|
+
resolve({
|
|
24
|
+
moduleDirectories: ["node_modules"],
|
|
25
|
+
browser: true,
|
|
26
|
+
}),
|
|
27
|
+
typescript({
|
|
28
|
+
tsconfig: "./tsconfig.json",
|
|
29
|
+
declaration: true,
|
|
30
|
+
outDir: "./dist/browser",
|
|
31
|
+
declarationDir: "./dist/browser",
|
|
32
|
+
}),
|
|
33
|
+
unpluginFragno({ platform: "browser" }),
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
// Node build
|
|
37
|
+
{
|
|
38
|
+
input: "./src/index.ts",
|
|
39
|
+
output: {
|
|
40
|
+
dir: "./dist/node",
|
|
41
|
+
format: "es",
|
|
42
|
+
sourcemap: true,
|
|
43
|
+
},
|
|
44
|
+
external: ["zod"],
|
|
45
|
+
plugins: [
|
|
46
|
+
resolve({
|
|
47
|
+
moduleDirectories: ["node_modules"],
|
|
48
|
+
}),
|
|
49
|
+
typescript({
|
|
50
|
+
tsconfig: "./tsconfig.json",
|
|
51
|
+
declaration: true,
|
|
52
|
+
outDir: "./dist/node",
|
|
53
|
+
declarationDir: "./dist/node",
|
|
54
|
+
}),
|
|
55
|
+
unpluginFragno({ platform: "node" }),
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import unpluginFragno from "@fragno-dev/unplugin-fragno/rspack";
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
|
|
7
|
+
/** @type {import('@rspack/core').Configuration[]} */
|
|
8
|
+
export default [
|
|
9
|
+
// Browser build
|
|
10
|
+
{
|
|
11
|
+
name: "browser",
|
|
12
|
+
mode: "production",
|
|
13
|
+
entry: {
|
|
14
|
+
index: "./src/index.ts",
|
|
15
|
+
"client/react": "./src/client/react.ts",
|
|
16
|
+
"client/svelte": "./src/client/svelte.ts",
|
|
17
|
+
"client/vanilla": "./src/client/vanilla.ts",
|
|
18
|
+
"client/vue": "./src/client/vue.ts",
|
|
19
|
+
},
|
|
20
|
+
output: {
|
|
21
|
+
path: path.resolve(__dirname, "dist/browser"),
|
|
22
|
+
filename: "[name].js",
|
|
23
|
+
library: {
|
|
24
|
+
type: "module",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
experiments: {
|
|
28
|
+
outputModule: true,
|
|
29
|
+
},
|
|
30
|
+
resolve: {
|
|
31
|
+
extensions: [".ts", ".js"],
|
|
32
|
+
},
|
|
33
|
+
module: {
|
|
34
|
+
rules: [
|
|
35
|
+
{
|
|
36
|
+
test: /\.ts$/,
|
|
37
|
+
use: "builtin:swc-loader",
|
|
38
|
+
exclude: /node_modules/,
|
|
39
|
+
options: {
|
|
40
|
+
jsc: {
|
|
41
|
+
parser: {
|
|
42
|
+
syntax: "typescript",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
plugins: [unpluginFragno({ platform: "browser" })],
|
|
50
|
+
devtool: "source-map",
|
|
51
|
+
externals: ["zod", "react", "vue", "svelte"],
|
|
52
|
+
},
|
|
53
|
+
// Node build
|
|
54
|
+
{
|
|
55
|
+
name: "node",
|
|
56
|
+
mode: "production",
|
|
57
|
+
entry: {
|
|
58
|
+
index: "./src/index.ts",
|
|
59
|
+
},
|
|
60
|
+
output: {
|
|
61
|
+
path: path.resolve(__dirname, "dist/node"),
|
|
62
|
+
filename: "[name].js",
|
|
63
|
+
library: {
|
|
64
|
+
type: "module",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
experiments: {
|
|
68
|
+
outputModule: true,
|
|
69
|
+
},
|
|
70
|
+
resolve: {
|
|
71
|
+
extensions: [".ts", ".js"],
|
|
72
|
+
},
|
|
73
|
+
module: {
|
|
74
|
+
rules: [
|
|
75
|
+
{
|
|
76
|
+
test: /\.ts$/,
|
|
77
|
+
use: "builtin:swc-loader",
|
|
78
|
+
exclude: /node_modules/,
|
|
79
|
+
options: {
|
|
80
|
+
jsc: {
|
|
81
|
+
parser: {
|
|
82
|
+
syntax: "typescript",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
plugins: [unpluginFragno({ platform: "node" })],
|
|
90
|
+
devtool: "source-map",
|
|
91
|
+
externals: ["zod"],
|
|
92
|
+
},
|
|
93
|
+
];
|