@fragno-dev/core 0.1.8 → 0.1.9
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 +131 -56
- package/CHANGELOG.md +13 -0
- package/dist/api/api.d.ts +38 -2
- package/dist/api/api.d.ts.map +1 -0
- package/dist/api/api.js +9 -3
- package/dist/api/api.js.map +1 -0
- package/dist/api/bind-services.d.ts +6 -0
- package/dist/api/bind-services.d.ts.map +1 -0
- package/dist/api/bind-services.js +20 -0
- package/dist/api/bind-services.js.map +1 -0
- package/dist/api/error.d.ts +26 -0
- package/dist/api/error.d.ts.map +1 -0
- package/dist/api/error.js +48 -0
- package/dist/api/error.js.map +1 -0
- package/dist/api/fragment-definition-builder.d.ts +313 -0
- package/dist/api/fragment-definition-builder.d.ts.map +1 -0
- package/dist/api/fragment-definition-builder.js +326 -0
- package/dist/api/fragment-definition-builder.js.map +1 -0
- package/dist/api/fragment-instantiator.d.ts +216 -0
- package/dist/api/fragment-instantiator.d.ts.map +1 -0
- package/dist/api/fragment-instantiator.js +487 -0
- package/dist/api/fragment-instantiator.js.map +1 -0
- package/dist/api/fragno-response.d.ts +30 -0
- package/dist/api/fragno-response.d.ts.map +1 -0
- package/dist/api/fragno-response.js +73 -0
- package/dist/api/fragno-response.js.map +1 -0
- package/dist/api/internal/path.d.ts +50 -0
- package/dist/api/internal/path.d.ts.map +1 -0
- package/dist/api/internal/path.js +76 -0
- package/dist/api/internal/path.js.map +1 -0
- package/dist/api/internal/response-stream.d.ts +43 -0
- package/dist/api/internal/response-stream.d.ts.map +1 -0
- package/dist/api/internal/response-stream.js +81 -0
- package/dist/api/internal/response-stream.js.map +1 -0
- package/dist/api/internal/route.js +10 -0
- package/dist/api/internal/route.js.map +1 -0
- package/dist/api/mutable-request-state.d.ts +82 -0
- package/dist/api/mutable-request-state.d.ts.map +1 -0
- package/dist/api/mutable-request-state.js +97 -0
- package/dist/api/mutable-request-state.js.map +1 -0
- package/dist/api/request-context-storage.d.ts +42 -0
- package/dist/api/request-context-storage.d.ts.map +1 -0
- package/dist/api/request-context-storage.js +43 -0
- package/dist/api/request-context-storage.js.map +1 -0
- package/dist/api/request-input-context.d.ts +89 -0
- package/dist/api/request-input-context.d.ts.map +1 -0
- package/dist/api/request-input-context.js +118 -0
- package/dist/api/request-input-context.js.map +1 -0
- package/dist/api/request-middleware.d.ts +50 -0
- package/dist/api/request-middleware.d.ts.map +1 -0
- package/dist/api/request-middleware.js +83 -0
- package/dist/api/request-middleware.js.map +1 -0
- package/dist/api/request-output-context.d.ts +41 -0
- package/dist/api/request-output-context.d.ts.map +1 -0
- package/dist/api/request-output-context.js +119 -0
- package/dist/api/request-output-context.js.map +1 -0
- package/dist/api/route-handler-input-options.d.ts +21 -0
- package/dist/api/route-handler-input-options.d.ts.map +1 -0
- package/dist/api/route.d.ts +54 -2
- package/dist/api/route.d.ts.map +1 -0
- package/dist/api/route.js +29 -2
- package/dist/api/route.js.map +1 -0
- package/dist/api/shared-types.d.ts +47 -0
- package/dist/api/shared-types.d.ts.map +1 -0
- package/dist/api/shared-types.js +1 -0
- package/dist/client/client-error.d.ts +60 -0
- package/dist/client/client-error.d.ts.map +1 -0
- package/dist/client/client-error.js +92 -0
- package/dist/client/client-error.js.map +1 -0
- package/dist/client/client.d.ts +210 -2
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +397 -5
- package/dist/client/client.js.map +1 -0
- package/dist/client/client.svelte.d.ts +5 -2
- package/dist/client/client.svelte.d.ts.map +1 -1
- package/dist/client/client.svelte.js +1 -4
- package/dist/client/client.svelte.js.map +1 -1
- package/dist/client/internal/fetcher-merge.js +36 -0
- package/dist/client/internal/fetcher-merge.js.map +1 -0
- package/dist/client/internal/ndjson-streaming.js +139 -0
- package/dist/client/internal/ndjson-streaming.js.map +1 -0
- package/dist/client/react.d.ts +5 -2
- package/dist/client/react.d.ts.map +1 -1
- package/dist/client/react.js +3 -4
- package/dist/client/react.js.map +1 -1
- package/dist/client/solid.d.ts +5 -2
- package/dist/client/solid.d.ts.map +1 -1
- package/dist/client/solid.js +2 -4
- package/dist/client/solid.js.map +1 -1
- package/dist/client/vanilla.d.ts +5 -2
- package/dist/client/vanilla.d.ts.map +1 -1
- package/dist/client/vanilla.js +2 -42
- package/dist/client/vanilla.js.map +1 -1
- package/dist/client/vue.d.ts +5 -2
- package/dist/client/vue.d.ts.map +1 -1
- package/dist/client/vue.js +1 -4
- package/dist/client/vue.js.map +1 -1
- package/dist/http/http-status.d.ts +26 -0
- package/dist/http/http-status.d.ts.map +1 -0
- package/dist/integrations/react-ssr.js +1 -1
- package/dist/internal/symbols.d.ts +9 -0
- package/dist/internal/symbols.d.ts.map +1 -0
- package/dist/internal/symbols.js +10 -0
- package/dist/internal/symbols.js.map +1 -0
- package/dist/mod-client.d.ts +36 -0
- package/dist/mod-client.d.ts.map +1 -0
- package/dist/mod-client.js +21 -0
- package/dist/mod-client.js.map +1 -0
- package/dist/mod.d.ts +7 -2
- package/dist/mod.js +4 -4
- package/dist/request/request.d.ts +4 -0
- package/dist/request/request.js +5 -0
- package/dist/test/test.d.ts +62 -34
- package/dist/test/test.d.ts.map +1 -1
- package/dist/test/test.js +75 -42
- package/dist/test/test.js.map +1 -1
- package/dist/util/async.js +40 -0
- package/dist/util/async.js.map +1 -0
- package/dist/util/content-type.js +49 -0
- package/dist/util/content-type.js.map +1 -0
- package/dist/util/nanostores.js +31 -0
- package/dist/util/nanostores.js.map +1 -0
- package/dist/{ssr-kyKI7pqH.js → util/ssr.js} +2 -2
- package/dist/util/ssr.js.map +1 -0
- package/dist/util/types-util.d.ts +8 -0
- package/dist/util/types-util.d.ts.map +1 -0
- package/package.json +19 -12
- package/src/api/api.ts +1 -5
- package/src/api/bind-services.ts +42 -0
- package/src/api/fragment-definition-builder.extend.test.ts +810 -0
- package/src/api/fragment-definition-builder.test.ts +499 -0
- package/src/api/fragment-definition-builder.ts +1088 -0
- package/src/api/fragment-instantiator.test.ts +1488 -0
- package/src/api/fragment-instantiator.ts +1053 -0
- package/src/api/fragment-services.test.ts +454 -189
- package/src/api/request-context-storage.ts +64 -0
- package/src/api/request-middleware.test.ts +301 -228
- package/src/api/route.test.ts +12 -36
- package/src/api/route.ts +167 -155
- package/src/api/shared-types.ts +43 -0
- package/src/client/client-builder.test.ts +23 -23
- package/src/client/client.ssr.test.ts +3 -3
- package/src/client/client.svelte.test.ts +15 -15
- package/src/client/client.test.ts +22 -22
- package/src/client/client.ts +72 -12
- package/src/client/internal/fetcher-merge.ts +1 -1
- package/src/client/react.test.ts +2 -2
- package/src/client/solid.test.ts +2 -2
- package/src/client/vanilla.test.ts +2 -2
- package/src/client/vue.test.ts +2 -2
- package/src/internal/symbols.ts +5 -0
- package/src/mod-client.ts +59 -0
- package/src/mod.ts +22 -15
- package/src/request/request.ts +8 -0
- package/src/test/test.test.ts +189 -375
- package/src/test/test.ts +186 -152
- package/tsdown.config.ts +8 -5
- package/dist/api/fragment-builder.d.ts +0 -2
- package/dist/api/fragment-builder.js +0 -3
- package/dist/api/fragment-instantiation.d.ts +0 -2
- package/dist/api/fragment-instantiation.js +0 -4
- package/dist/api-BFrUCIsF.d.ts +0 -963
- package/dist/api-BFrUCIsF.d.ts.map +0 -1
- package/dist/client-DAFHcKqA.js +0 -782
- package/dist/client-DAFHcKqA.js.map +0 -1
- package/dist/fragment-builder-Boh2vNHq.js +0 -108
- package/dist/fragment-builder-Boh2vNHq.js.map +0 -1
- package/dist/fragment-instantiation-DUT-HLl1.js +0 -898
- package/dist/fragment-instantiation-DUT-HLl1.js.map +0 -1
- package/dist/route-C4CyNHkC.js +0 -26
- package/dist/route-C4CyNHkC.js.map +0 -1
- package/dist/ssr-kyKI7pqH.js.map +0 -1
- package/src/api/fragment-builder.ts +0 -518
- package/src/api/fragment-instantiation.test.ts +0 -702
- package/src/api/fragment-instantiation.ts +0 -766
- package/src/api/fragment.test.ts +0 -585
package/src/api/route.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { test, expect, expectTypeOf, describe } from "vitest";
|
|
2
|
-
import { defineRoute, defineRoutes
|
|
3
|
-
import { defineFragment } from "./fragment-builder";
|
|
2
|
+
import { defineRoute, defineRoutes } from "./route";
|
|
3
|
+
import { defineFragment } from "./fragment-definition-builder";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
6
6
|
describe("defineRoute", () => {
|
|
@@ -176,43 +176,18 @@ describe("defineRoute", () => {
|
|
|
176
176
|
});
|
|
177
177
|
});
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
// ExtractFragmentServices tests removed - use ExtractFragmentServices instead
|
|
180
|
+
|
|
181
|
+
describe("defineRoutes", () => {
|
|
182
|
+
test("defineRoutes extracts services correctly for route factory", () => {
|
|
181
183
|
const fragment = defineFragment<{}>("test-fragment")
|
|
182
|
-
.
|
|
183
|
-
.providesService(({ defineService }) =>
|
|
184
|
+
.providesBaseService(({ defineService }) =>
|
|
184
185
|
defineService({
|
|
185
186
|
getUserById: async (id: string) => ({ id, name: "John" }),
|
|
186
187
|
createUser: async (name: string) => ({ id: "123", name }),
|
|
187
188
|
}),
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
type Services = ExtractFragmentServices<typeof fragment>;
|
|
191
|
-
|
|
192
|
-
expectTypeOf<Services>().toMatchObjectType<{
|
|
193
|
-
getUserById: (id: string) => Promise<{ id: string; name: string }>;
|
|
194
|
-
createUser: (name: string) => Promise<{ id: string; name: string }>;
|
|
195
|
-
}>();
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
test("ExtractFragmentServices returns never for fragment without services", () => {
|
|
199
|
-
const fragment = defineFragment<{}>("test-fragment").withDependencies(() => ({ dep: "value" }));
|
|
200
|
-
|
|
201
|
-
type Services = ExtractFragmentServices<typeof fragment>;
|
|
202
|
-
|
|
203
|
-
// Fragment with no services should have empty services object
|
|
204
|
-
expectTypeOf<Services>().toEqualTypeOf<{}>();
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
describe("defineRoutes", () => {
|
|
209
|
-
test("defineRoutes extracts services correctly for route factory", () => {
|
|
210
|
-
const fragment = defineFragment<{}>("test-fragment").providesService(({ defineService }) =>
|
|
211
|
-
defineService({
|
|
212
|
-
getUserById: async (id: string) => ({ id, name: "John" }),
|
|
213
|
-
createUser: async (name: string) => ({ id: "123", name }),
|
|
214
|
-
}),
|
|
215
|
-
);
|
|
189
|
+
)
|
|
190
|
+
.build();
|
|
216
191
|
|
|
217
192
|
const routeFactory = defineRoutes(fragment).create(({ services, config, deps }) => {
|
|
218
193
|
// Type check that services are properly extracted
|
|
@@ -248,13 +223,14 @@ describe("defineRoutes", () => {
|
|
|
248
223
|
.withDependencies(({ config }) => ({
|
|
249
224
|
authClient: { apiKey: config.apiKey },
|
|
250
225
|
}))
|
|
251
|
-
.
|
|
226
|
+
.providesBaseService(({ deps, defineService }) =>
|
|
252
227
|
defineService({
|
|
253
228
|
validateToken: async (_token: string) => {
|
|
254
229
|
return { valid: true, apiKey: deps.authClient.apiKey };
|
|
255
230
|
},
|
|
256
231
|
}),
|
|
257
|
-
)
|
|
232
|
+
)
|
|
233
|
+
.build();
|
|
258
234
|
|
|
259
235
|
const routeFactory = defineRoutes(fragment).create(({ services, config, deps }) => {
|
|
260
236
|
// Type check all context properties
|
package/src/api/route.ts
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
|
+
// oxlint-disable no-explicit-any
|
|
2
|
+
|
|
1
3
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
4
|
import type { FragnoRouteConfig, HTTPMethod, RequestThisContext } from "./api";
|
|
3
|
-
import type { FragmentDefinition } from "./fragment-builder";
|
|
5
|
+
import type { FragmentDefinition } from "./fragment-definition-builder";
|
|
6
|
+
import type { BoundServices } from "./bind-services";
|
|
4
7
|
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
8
|
export type AnyFragnoRouteConfig = FragnoRouteConfig<HTTPMethod, string, any, any, any, any, any>;
|
|
7
9
|
|
|
8
|
-
export
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
-
readonly definition: FragmentDefinition<any, any, any, any, any, any, any>;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export interface RouteFactoryContext<TConfig, TDeps, TServices> {
|
|
10
|
+
export interface RouteFactoryContext<TConfig, TDeps, TServices, TServiceDeps = {}> {
|
|
14
11
|
config: TConfig;
|
|
15
12
|
deps: TDeps;
|
|
16
13
|
services: TServices;
|
|
14
|
+
serviceDeps: TServiceDeps;
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
export type RouteFactory<
|
|
20
18
|
TConfig,
|
|
21
19
|
TDeps,
|
|
22
20
|
TServices,
|
|
21
|
+
TServiceDeps,
|
|
23
22
|
TRoutes extends readonly FragnoRouteConfig<
|
|
24
23
|
HTTPMethod,
|
|
25
24
|
string,
|
|
@@ -29,32 +28,39 @@ export type RouteFactory<
|
|
|
29
28
|
string,
|
|
30
29
|
RequestThisContext
|
|
31
30
|
>[],
|
|
32
|
-
> = (context: RouteFactoryContext<TConfig, TDeps, TServices>) => TRoutes;
|
|
31
|
+
> = (context: RouteFactoryContext<TConfig, TDeps, TServices, TServiceDeps>) => TRoutes;
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
/**
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export type AnyRouteOrFactory = AnyFragnoRouteConfig | RouteFactory<any, any, any, any, any>;
|
|
36
37
|
|
|
38
|
+
/**
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
37
41
|
export type FlattenRouteFactories<T extends readonly AnyRouteOrFactory[]> = T extends readonly [
|
|
38
42
|
infer First,
|
|
39
43
|
...infer Rest extends readonly AnyRouteOrFactory[],
|
|
40
44
|
]
|
|
41
|
-
?
|
|
42
|
-
First extends RouteFactory<any, any, any, infer TRoutes>
|
|
45
|
+
? First extends RouteFactory<any, any, any, any, infer TRoutes>
|
|
43
46
|
? [...TRoutes, ...FlattenRouteFactories<Rest>]
|
|
44
47
|
: [First, ...FlattenRouteFactories<Rest>]
|
|
45
48
|
: [];
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Helper to resolve route factories into routes
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
48
54
|
export function resolveRouteFactories<
|
|
49
55
|
TConfig,
|
|
50
56
|
TDeps,
|
|
51
57
|
TServices,
|
|
58
|
+
TServiceDeps,
|
|
52
59
|
const TRoutesOrFactories extends readonly AnyRouteOrFactory[],
|
|
53
60
|
>(
|
|
54
|
-
context: RouteFactoryContext<TConfig, TDeps, TServices>,
|
|
61
|
+
context: RouteFactoryContext<TConfig, TDeps, TServices, TServiceDeps>,
|
|
55
62
|
routesOrFactories: TRoutesOrFactories,
|
|
56
63
|
): FlattenRouteFactories<TRoutesOrFactories> {
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
64
|
const routes: any[] = [];
|
|
59
65
|
|
|
60
66
|
for (const item of routesOrFactories) {
|
|
@@ -162,107 +168,111 @@ export function defineRoute<
|
|
|
162
168
|
return config;
|
|
163
169
|
}
|
|
164
170
|
|
|
165
|
-
//
|
|
166
|
-
//
|
|
167
|
-
//
|
|
171
|
+
// ============================================================================
|
|
172
|
+
// Type extractors for FragmentDefinition
|
|
173
|
+
// ============================================================================
|
|
168
174
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
export type AnyFragmentDefinition = FragmentDefinition<
|
|
176
|
+
any,
|
|
177
|
+
any,
|
|
178
|
+
any,
|
|
179
|
+
any,
|
|
180
|
+
any,
|
|
181
|
+
any,
|
|
182
|
+
any,
|
|
183
|
+
any,
|
|
184
|
+
any,
|
|
185
|
+
any
|
|
186
|
+
>;
|
|
172
187
|
|
|
173
|
-
// Extract config
|
|
188
|
+
// Extract config from FragmentDefinition
|
|
174
189
|
export type ExtractFragmentConfig<T> =
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
190
|
+
T extends FragmentDefinition<infer TConfig, any, any, any, any, any, any, any, any, any>
|
|
191
|
+
? TConfig
|
|
192
|
+
: never;
|
|
193
|
+
|
|
194
|
+
// Extract deps from FragmentDefinition
|
|
195
|
+
export type ExtractFragmentDeps<T> =
|
|
196
|
+
T extends FragmentDefinition<any, any, infer TDeps, any, any, any, any, any, any, any>
|
|
197
|
+
? TDeps
|
|
198
|
+
: never;
|
|
199
|
+
|
|
200
|
+
// Extract services from FragmentDefinition
|
|
201
|
+
// This extracts both base services (flat) and named services (nested)
|
|
202
|
+
// The result matches the structure of fragment.services at runtime
|
|
203
|
+
export type ExtractFragmentServices<T> =
|
|
204
|
+
T extends FragmentDefinition<
|
|
205
|
+
any,
|
|
206
|
+
any,
|
|
207
|
+
any,
|
|
208
|
+
infer TBaseServices,
|
|
209
|
+
infer TServices,
|
|
178
210
|
any,
|
|
179
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
180
211
|
any,
|
|
181
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
182
212
|
any,
|
|
183
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
184
213
|
any,
|
|
185
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
186
214
|
any
|
|
187
215
|
>
|
|
188
|
-
?
|
|
216
|
+
? BoundServices<TBaseServices & TServices>
|
|
189
217
|
: never;
|
|
190
218
|
|
|
191
|
-
// Extract
|
|
192
|
-
export type
|
|
193
|
-
|
|
194
|
-
|
|
219
|
+
// Extract service dependencies from FragmentDefinition
|
|
220
|
+
export type ExtractFragmentServiceDeps<T> =
|
|
221
|
+
T extends FragmentDefinition<
|
|
222
|
+
any,
|
|
223
|
+
any,
|
|
224
|
+
any,
|
|
225
|
+
any,
|
|
226
|
+
any,
|
|
227
|
+
infer TServiceDependencies,
|
|
195
228
|
any,
|
|
196
|
-
infer TDeps,
|
|
197
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
198
229
|
any,
|
|
199
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
200
230
|
any,
|
|
201
|
-
infer TUsedServices,
|
|
202
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
203
231
|
any
|
|
204
232
|
>
|
|
205
|
-
?
|
|
233
|
+
? TServiceDependencies
|
|
206
234
|
: never;
|
|
207
235
|
|
|
208
|
-
//
|
|
209
|
-
type
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
export type ExtractFragmentServices<T> = T extends {
|
|
225
|
-
$types: { services: infer S; providedServices: infer P };
|
|
226
|
-
}
|
|
227
|
-
? BoundServicesLocal<S & P>
|
|
228
|
-
: GetDefinition<T> extends FragmentDefinition<
|
|
229
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
230
|
-
any,
|
|
231
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
232
|
-
any,
|
|
233
|
-
infer TServices,
|
|
234
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
235
|
-
any,
|
|
236
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
237
|
-
any,
|
|
238
|
-
infer TProvidedServices
|
|
239
|
-
>
|
|
240
|
-
? TServices & TProvidedServices
|
|
241
|
-
: never;
|
|
236
|
+
// Extract service this context from FragmentDefinition (used by services)
|
|
237
|
+
export type ExtractFragmentServiceThisContext<T> =
|
|
238
|
+
T extends FragmentDefinition<
|
|
239
|
+
any,
|
|
240
|
+
any,
|
|
241
|
+
any,
|
|
242
|
+
any,
|
|
243
|
+
any,
|
|
244
|
+
any,
|
|
245
|
+
any,
|
|
246
|
+
infer TServiceThisContext,
|
|
247
|
+
any,
|
|
248
|
+
any
|
|
249
|
+
>
|
|
250
|
+
? TServiceThisContext
|
|
251
|
+
: RequestThisContext;
|
|
242
252
|
|
|
243
|
-
// Extract
|
|
244
|
-
export type
|
|
245
|
-
|
|
246
|
-
|
|
253
|
+
// Extract handler this context from FragmentDefinition (used by route handlers)
|
|
254
|
+
export type ExtractFragmentHandlerThisContext<T> =
|
|
255
|
+
T extends FragmentDefinition<
|
|
256
|
+
any,
|
|
247
257
|
any,
|
|
248
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
249
258
|
any,
|
|
250
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
251
259
|
any,
|
|
252
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
253
260
|
any,
|
|
254
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
255
261
|
any,
|
|
256
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
257
262
|
any,
|
|
258
|
-
|
|
263
|
+
any,
|
|
264
|
+
infer THandlerThisContext,
|
|
265
|
+
any
|
|
259
266
|
>
|
|
260
|
-
?
|
|
267
|
+
? THandlerThisContext
|
|
261
268
|
: RequestThisContext;
|
|
262
269
|
|
|
263
|
-
//
|
|
264
|
-
export
|
|
265
|
-
|
|
270
|
+
// Legacy: Extract this context from FragmentDefinition (defaults to service context for backwards compatibility)
|
|
271
|
+
export type ExtractFragmentThisContext<T> = ExtractFragmentServiceThisContext<T>;
|
|
272
|
+
|
|
273
|
+
// Overload that infers types from FragmentDefinition (runtime value)
|
|
274
|
+
export function defineRoutes<const TDefinition extends AnyFragmentDefinition>(
|
|
275
|
+
definition: TDefinition,
|
|
266
276
|
): {
|
|
267
277
|
create: <
|
|
268
278
|
const TRoutes extends readonly FragnoRouteConfig<
|
|
@@ -272,14 +282,15 @@ export function defineRoutes<const TFragmentBuilder extends AnyFragmentBuilder>(
|
|
|
272
282
|
StandardSchemaV1 | undefined,
|
|
273
283
|
string,
|
|
274
284
|
string,
|
|
275
|
-
|
|
285
|
+
ExtractFragmentHandlerThisContext<TDefinition>
|
|
276
286
|
>[],
|
|
277
287
|
>(
|
|
278
288
|
fn: (
|
|
279
289
|
context: RouteFactoryContext<
|
|
280
|
-
ExtractFragmentConfig<
|
|
281
|
-
ExtractFragmentDeps<
|
|
282
|
-
ExtractFragmentServices<
|
|
290
|
+
ExtractFragmentConfig<TDefinition>,
|
|
291
|
+
ExtractFragmentDeps<TDefinition>,
|
|
292
|
+
ExtractFragmentServices<TDefinition>,
|
|
293
|
+
ExtractFragmentServiceDeps<TDefinition>
|
|
283
294
|
> & {
|
|
284
295
|
defineRoute: <
|
|
285
296
|
const TMethod extends HTTPMethod,
|
|
@@ -296,7 +307,7 @@ export function defineRoutes<const TFragmentBuilder extends AnyFragmentBuilder>(
|
|
|
296
307
|
TOutputSchema,
|
|
297
308
|
TErrorCode,
|
|
298
309
|
TQueryParameters,
|
|
299
|
-
|
|
310
|
+
ExtractFragmentHandlerThisContext<TDefinition>
|
|
300
311
|
>,
|
|
301
312
|
) => FragnoRouteConfig<
|
|
302
313
|
TMethod,
|
|
@@ -305,20 +316,21 @@ export function defineRoutes<const TFragmentBuilder extends AnyFragmentBuilder>(
|
|
|
305
316
|
TOutputSchema,
|
|
306
317
|
TErrorCode,
|
|
307
318
|
TQueryParameters,
|
|
308
|
-
|
|
319
|
+
ExtractFragmentHandlerThisContext<TDefinition>
|
|
309
320
|
>;
|
|
310
321
|
},
|
|
311
322
|
) => TRoutes,
|
|
312
323
|
) => RouteFactory<
|
|
313
|
-
ExtractFragmentConfig<
|
|
314
|
-
ExtractFragmentDeps<
|
|
315
|
-
ExtractFragmentServices<
|
|
324
|
+
ExtractFragmentConfig<TDefinition>,
|
|
325
|
+
ExtractFragmentDeps<TDefinition>,
|
|
326
|
+
ExtractFragmentServices<TDefinition>,
|
|
327
|
+
ExtractFragmentServiceDeps<TDefinition>,
|
|
316
328
|
TRoutes
|
|
317
329
|
>;
|
|
318
330
|
};
|
|
319
331
|
|
|
320
|
-
// Overload that infers types from
|
|
321
|
-
export function defineRoutes<const
|
|
332
|
+
// Overload that infers types from FragmentDefinition (type parameter only)
|
|
333
|
+
export function defineRoutes<const TDefinition extends AnyFragmentDefinition>(): {
|
|
322
334
|
create: <
|
|
323
335
|
const TRoutes extends readonly FragnoRouteConfig<
|
|
324
336
|
HTTPMethod,
|
|
@@ -327,14 +339,15 @@ export function defineRoutes<const TFragmentBuilder extends AnyFragmentBuilder>(
|
|
|
327
339
|
StandardSchemaV1 | undefined,
|
|
328
340
|
string,
|
|
329
341
|
string,
|
|
330
|
-
|
|
342
|
+
ExtractFragmentHandlerThisContext<TDefinition>
|
|
331
343
|
>[],
|
|
332
344
|
>(
|
|
333
345
|
fn: (
|
|
334
346
|
context: RouteFactoryContext<
|
|
335
|
-
ExtractFragmentConfig<
|
|
336
|
-
ExtractFragmentDeps<
|
|
337
|
-
ExtractFragmentServices<
|
|
347
|
+
ExtractFragmentConfig<TDefinition>,
|
|
348
|
+
ExtractFragmentDeps<TDefinition>,
|
|
349
|
+
ExtractFragmentServices<TDefinition>,
|
|
350
|
+
ExtractFragmentServiceDeps<TDefinition>
|
|
338
351
|
> & {
|
|
339
352
|
defineRoute: <
|
|
340
353
|
const TMethod extends HTTPMethod,
|
|
@@ -351,7 +364,7 @@ export function defineRoutes<const TFragmentBuilder extends AnyFragmentBuilder>(
|
|
|
351
364
|
TOutputSchema,
|
|
352
365
|
TErrorCode,
|
|
353
366
|
TQueryParameters,
|
|
354
|
-
|
|
367
|
+
ExtractFragmentHandlerThisContext<TDefinition>
|
|
355
368
|
>,
|
|
356
369
|
) => FragnoRouteConfig<
|
|
357
370
|
TMethod,
|
|
@@ -360,48 +373,25 @@ export function defineRoutes<const TFragmentBuilder extends AnyFragmentBuilder>(
|
|
|
360
373
|
TOutputSchema,
|
|
361
374
|
TErrorCode,
|
|
362
375
|
TQueryParameters,
|
|
363
|
-
|
|
376
|
+
ExtractFragmentHandlerThisContext<TDefinition>
|
|
364
377
|
>;
|
|
365
378
|
},
|
|
366
379
|
) => TRoutes,
|
|
367
380
|
) => RouteFactory<
|
|
368
|
-
ExtractFragmentConfig<
|
|
369
|
-
ExtractFragmentDeps<
|
|
370
|
-
ExtractFragmentServices<
|
|
381
|
+
ExtractFragmentConfig<TDefinition>,
|
|
382
|
+
ExtractFragmentDeps<TDefinition>,
|
|
383
|
+
ExtractFragmentServices<TDefinition>,
|
|
384
|
+
ExtractFragmentServiceDeps<TDefinition>,
|
|
371
385
|
TRoutes
|
|
372
386
|
>;
|
|
373
387
|
};
|
|
374
388
|
|
|
375
|
-
// Overload that accepts manual type parameters
|
|
376
|
-
export function defineRoutes<TConfig = {}, TDeps = {}, TServices = {}>(): {
|
|
377
|
-
create: <
|
|
378
|
-
const TRoutes extends readonly FragnoRouteConfig<
|
|
379
|
-
HTTPMethod,
|
|
380
|
-
string,
|
|
381
|
-
StandardSchemaV1 | undefined,
|
|
382
|
-
StandardSchemaV1 | undefined,
|
|
383
|
-
string,
|
|
384
|
-
string,
|
|
385
|
-
RequestThisContext
|
|
386
|
-
>[],
|
|
387
|
-
>(
|
|
388
|
-
fn: (
|
|
389
|
-
context: RouteFactoryContext<TConfig, TDeps, TServices> & {
|
|
390
|
-
defineRoute: typeof defineRoute;
|
|
391
|
-
},
|
|
392
|
-
) => TRoutes,
|
|
393
|
-
) => RouteFactory<TConfig, TDeps, TServices, TRoutes>;
|
|
394
|
-
};
|
|
395
|
-
|
|
396
389
|
// Implementation
|
|
397
390
|
export function defineRoutes<
|
|
398
|
-
const
|
|
399
|
-
const TDeps = {},
|
|
400
|
-
const TServices = {},
|
|
401
|
-
const TFragmentBuilder extends AnyFragmentBuilder | undefined = undefined,
|
|
391
|
+
const TDefinition extends AnyFragmentDefinition | undefined = undefined,
|
|
402
392
|
>(
|
|
403
393
|
// Parameter is only used for type inference, not runtime
|
|
404
|
-
|
|
394
|
+
_definition?: TDefinition,
|
|
405
395
|
) {
|
|
406
396
|
return {
|
|
407
397
|
create: <
|
|
@@ -412,41 +402,63 @@ export function defineRoutes<
|
|
|
412
402
|
StandardSchemaV1 | undefined,
|
|
413
403
|
string,
|
|
414
404
|
string,
|
|
415
|
-
|
|
405
|
+
TDefinition extends AnyFragmentDefinition
|
|
406
|
+
? ExtractFragmentThisContext<TDefinition>
|
|
407
|
+
: RequestThisContext
|
|
416
408
|
>[],
|
|
417
409
|
>(
|
|
418
410
|
fn: (
|
|
419
411
|
context: RouteFactoryContext<
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
? ExtractFragmentDeps<TFragmentBuilder>
|
|
425
|
-
: TDeps,
|
|
426
|
-
TFragmentBuilder extends AnyFragmentBuilder
|
|
427
|
-
? ExtractFragmentServices<TFragmentBuilder>
|
|
428
|
-
: TServices
|
|
412
|
+
TDefinition extends AnyFragmentDefinition ? ExtractFragmentConfig<TDefinition> : {},
|
|
413
|
+
TDefinition extends AnyFragmentDefinition ? ExtractFragmentDeps<TDefinition> : {},
|
|
414
|
+
TDefinition extends AnyFragmentDefinition ? ExtractFragmentServices<TDefinition> : {},
|
|
415
|
+
TDefinition extends AnyFragmentDefinition ? ExtractFragmentServiceDeps<TDefinition> : {}
|
|
429
416
|
> & {
|
|
430
|
-
defineRoute:
|
|
417
|
+
defineRoute: <
|
|
418
|
+
const TMethod extends HTTPMethod,
|
|
419
|
+
const TPath extends string,
|
|
420
|
+
const TInputSchema extends StandardSchemaV1 | undefined,
|
|
421
|
+
const TOutputSchema extends StandardSchemaV1 | undefined,
|
|
422
|
+
const TErrorCode extends string = string,
|
|
423
|
+
const TQueryParameters extends string = string,
|
|
424
|
+
>(
|
|
425
|
+
config: FragnoRouteConfig<
|
|
426
|
+
TMethod,
|
|
427
|
+
TPath,
|
|
428
|
+
TInputSchema,
|
|
429
|
+
TOutputSchema,
|
|
430
|
+
TErrorCode,
|
|
431
|
+
TQueryParameters,
|
|
432
|
+
TDefinition extends AnyFragmentDefinition
|
|
433
|
+
? ExtractFragmentThisContext<TDefinition>
|
|
434
|
+
: RequestThisContext
|
|
435
|
+
>,
|
|
436
|
+
) => FragnoRouteConfig<
|
|
437
|
+
TMethod,
|
|
438
|
+
TPath,
|
|
439
|
+
TInputSchema,
|
|
440
|
+
TOutputSchema,
|
|
441
|
+
TErrorCode,
|
|
442
|
+
TQueryParameters,
|
|
443
|
+
TDefinition extends AnyFragmentDefinition
|
|
444
|
+
? ExtractFragmentThisContext<TDefinition>
|
|
445
|
+
: RequestThisContext
|
|
446
|
+
>;
|
|
431
447
|
},
|
|
432
448
|
) => TRoutes,
|
|
433
449
|
): RouteFactory<
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
TFragmentBuilder extends AnyFragmentBuilder
|
|
439
|
-
? ExtractFragmentServices<TFragmentBuilder>
|
|
440
|
-
: TServices,
|
|
450
|
+
TDefinition extends AnyFragmentDefinition ? ExtractFragmentConfig<TDefinition> : {},
|
|
451
|
+
TDefinition extends AnyFragmentDefinition ? ExtractFragmentDeps<TDefinition> : {},
|
|
452
|
+
TDefinition extends AnyFragmentDefinition ? ExtractFragmentServices<TDefinition> : {},
|
|
453
|
+
TDefinition extends AnyFragmentDefinition ? ExtractFragmentServiceDeps<TDefinition> : {},
|
|
441
454
|
TRoutes
|
|
442
455
|
> => {
|
|
443
456
|
// Create a wrapper around the callback that adds the defineRoute function
|
|
444
|
-
return (ctx: RouteFactoryContext<unknown, unknown, unknown>) => {
|
|
457
|
+
return (ctx: RouteFactoryContext<unknown, unknown, unknown, unknown>) => {
|
|
445
458
|
const extendedCtx = {
|
|
446
459
|
...ctx,
|
|
447
460
|
defineRoute,
|
|
448
461
|
};
|
|
449
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
450
462
|
return fn(extendedCtx as any);
|
|
451
463
|
};
|
|
452
464
|
},
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { HTTPMethod } from "./api";
|
|
2
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Public configuration for Fragno fragments on the server side.
|
|
6
|
+
*/
|
|
7
|
+
export interface FragnoPublicConfig {
|
|
8
|
+
mountRoute?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for custom fetch behavior in client-side fragments.
|
|
13
|
+
*/
|
|
14
|
+
export type FetcherConfig =
|
|
15
|
+
| { type: "options"; options: RequestInit }
|
|
16
|
+
| { type: "function"; fetcher: typeof fetch };
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Public configuration for Fragno fragments on the client side.
|
|
20
|
+
*/
|
|
21
|
+
export interface FragnoPublicClientConfig {
|
|
22
|
+
mountRoute?: string;
|
|
23
|
+
baseUrl?: string;
|
|
24
|
+
fetcherConfig?: FetcherConfig;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Shared configuration for fragment routes.
|
|
29
|
+
*/
|
|
30
|
+
export interface FragnoFragmentSharedConfig<
|
|
31
|
+
TRoutes extends readonly {
|
|
32
|
+
method: HTTPMethod;
|
|
33
|
+
path: string;
|
|
34
|
+
inputSchema?: StandardSchemaV1 | undefined;
|
|
35
|
+
outputSchema?: StandardSchemaV1 | undefined;
|
|
36
|
+
errorCodes?: readonly string[];
|
|
37
|
+
queryParameters?: readonly string[];
|
|
38
|
+
pathParameters?: readonly string[];
|
|
39
|
+
}[] = [],
|
|
40
|
+
> {
|
|
41
|
+
name: string;
|
|
42
|
+
routes: TRoutes;
|
|
43
|
+
}
|