@jay-framework/fullstack-component 0.9.0 → 0.10.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.
- package/README.md +371 -2
- package/dist/index.d.ts +469 -16
- package/dist/index.js +381 -11
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,31 @@ declare function createJayService<ServiceType = unknown>(name?: string): Service
|
|
|
30
30
|
type ServiceMarkers<T extends any[]> = {
|
|
31
31
|
[K in keyof T]: ServiceMarker<T[K]>;
|
|
32
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Contract metadata passed to dynamic contract components.
|
|
35
|
+
* Contains the contract name and original YAML definition.
|
|
36
|
+
*/
|
|
37
|
+
interface DynamicContractMetadata {
|
|
38
|
+
contractName: string;
|
|
39
|
+
contractYaml: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Built-in service for dynamic contract metadata.
|
|
43
|
+
* Used by plugin system to pass contract metadata to shared components.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* export const cmsCollection = makeJayStackComponent<DynamicContract>()
|
|
48
|
+
* .withServices(DYNAMIC_CONTRACT_SERVICE)
|
|
49
|
+
* .withFastRender(async (props, metadata: DynamicContractMetadata) => {
|
|
50
|
+
* // metadata.contractName contains the full contract name (e.g., "BlogPostsList")
|
|
51
|
+
* const collectionName = deriveCollectionName(metadata.contractName);
|
|
52
|
+
* const items = await fetchCollection(collectionName);
|
|
53
|
+
* return partialRender({ items }, {});
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare const DYNAMIC_CONTRACT_SERVICE: ServiceMarker<DynamicContractMetadata>;
|
|
33
58
|
interface PageProps {
|
|
34
59
|
language: string;
|
|
35
60
|
url: string;
|
|
@@ -38,24 +63,43 @@ type UrlParams = Record<string, string>;
|
|
|
38
63
|
interface ServerError5xx {
|
|
39
64
|
kind: 'ServerError';
|
|
40
65
|
status: number;
|
|
66
|
+
message?: string;
|
|
67
|
+
code?: string;
|
|
68
|
+
details?: Record<string, unknown>;
|
|
41
69
|
}
|
|
42
70
|
interface ClientError4xx {
|
|
43
71
|
kind: 'ClientError';
|
|
44
72
|
status: number;
|
|
73
|
+
message?: string;
|
|
74
|
+
code?: string;
|
|
75
|
+
details?: Record<string, unknown>;
|
|
45
76
|
}
|
|
46
77
|
interface Redirect3xx {
|
|
47
|
-
kind: '
|
|
78
|
+
kind: 'Redirect';
|
|
48
79
|
status: number;
|
|
49
80
|
location: string;
|
|
81
|
+
message?: string;
|
|
50
82
|
}
|
|
51
|
-
|
|
52
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Successful output of a rendering phase.
|
|
85
|
+
* Contains the rendered ViewState and data to carry forward to the next phase.
|
|
86
|
+
*/
|
|
87
|
+
interface PhaseOutput<ViewState extends object, CarryForward = {}> {
|
|
88
|
+
kind: 'PhaseOutput';
|
|
53
89
|
rendered: ViewState;
|
|
54
90
|
carryForward: CarryForward;
|
|
55
91
|
}
|
|
56
|
-
|
|
92
|
+
/**
|
|
93
|
+
* @deprecated Use PhaseOutput instead. PartialRender is kept for backwards compatibility.
|
|
94
|
+
*/
|
|
95
|
+
type PartialRender<ViewState extends object, CarryForward> = PhaseOutput<ViewState, CarryForward>;
|
|
96
|
+
/**
|
|
97
|
+
* Union of all possible render outcomes.
|
|
98
|
+
*/
|
|
99
|
+
type RenderOutcome<ViewState extends object, CarryForward = {}> = PhaseOutput<ViewState, CarryForward> | ServerError5xx | ClientError4xx | Redirect3xx;
|
|
100
|
+
type SlowlyRenderResult<ViewState extends object, CarryForward = {}> = RenderOutcome<ViewState, CarryForward>;
|
|
57
101
|
type AnySlowlyRenderResult = SlowlyRenderResult<object, object>;
|
|
58
|
-
type FastRenderResult<ViewState extends object, CarryForward> =
|
|
102
|
+
type FastRenderResult<ViewState extends object, CarryForward = {}> = RenderOutcome<ViewState, CarryForward>;
|
|
59
103
|
type AnyFastRenderResult = FastRenderResult<object, object>;
|
|
60
104
|
type LoadParams<Services, Params extends UrlParams> = (contexts: Services) => AsyncIterable<Params[]>;
|
|
61
105
|
type RenderSlowly<Services extends Array<object>, PropsT extends object, SlowViewState extends object, SlowlyCarryForward> = (props: PropsT, ...services: Services) => Promise<SlowlyRenderResult<SlowViewState, SlowlyCarryForward>>;
|
|
@@ -69,12 +113,51 @@ interface JayStackComponentDefinition<Refs extends object, SlowVS extends object
|
|
|
69
113
|
comp: ComponentConstructor<PropsT, Refs, InteractiveVS, Contexts, CompCore>;
|
|
70
114
|
}
|
|
71
115
|
type AnyJayStackComponentDefinition = JayStackComponentDefinition<object, object, object, object, object[], object[], object, UrlParams, any>;
|
|
116
|
+
/**
|
|
117
|
+
* A generated contract definition in YAML string format.
|
|
118
|
+
*
|
|
119
|
+
* This avoids dependency on compiler types - generators output contract YAML,
|
|
120
|
+
* which the compiler parses using its own type system.
|
|
121
|
+
*/
|
|
122
|
+
interface GeneratedContractYaml {
|
|
123
|
+
name: string;
|
|
124
|
+
yaml: string;
|
|
125
|
+
description?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Function that generates contracts dynamically at build time.
|
|
129
|
+
* Returns contract definitions as YAML strings to avoid compiler type dependencies.
|
|
130
|
+
* Services are injected based on the markers provided to withServices().
|
|
131
|
+
*/
|
|
132
|
+
type ContractGeneratorFunction<Services extends any[]> = (...services: Services) => Promise<GeneratedContractYaml[]> | GeneratedContractYaml[];
|
|
133
|
+
/**
|
|
134
|
+
* Interface for a dynamic contract generator with service dependencies.
|
|
135
|
+
* Returned by makeContractGenerator() builder.
|
|
136
|
+
*/
|
|
137
|
+
interface DynamicContractGenerator<Services extends any[] = any[]> {
|
|
138
|
+
services: ServiceMarkers<Services>;
|
|
139
|
+
generate: ContractGeneratorFunction<Services>;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Type helper to extract service instances from service markers.
|
|
143
|
+
*/
|
|
144
|
+
type ServiceInstances<Markers extends ServiceMarkers<any[]>> = Markers extends ServiceMarkers<infer Services> ? Services : never;
|
|
72
145
|
|
|
73
|
-
declare function serverError5xx(status: number): ServerError5xx;
|
|
74
|
-
declare function clientError4xx(status: number): ClientError4xx;
|
|
75
|
-
declare function notFound(): ClientError4xx;
|
|
76
|
-
declare function
|
|
77
|
-
declare function
|
|
146
|
+
declare function serverError5xx(status: number, message?: string, details?: Record<string, unknown>): ServerError5xx;
|
|
147
|
+
declare function clientError4xx(status: number, message?: string, details?: Record<string, unknown>): ClientError4xx;
|
|
148
|
+
declare function notFound(message?: string, details?: Record<string, unknown>): ClientError4xx;
|
|
149
|
+
declare function badRequest(message?: string, details?: Record<string, unknown>): ClientError4xx;
|
|
150
|
+
declare function unauthorized(message?: string, details?: Record<string, unknown>): ClientError4xx;
|
|
151
|
+
declare function forbidden(message?: string, details?: Record<string, unknown>): ClientError4xx;
|
|
152
|
+
declare function redirect3xx(status: number, location: string, message?: string): Redirect3xx;
|
|
153
|
+
/**
|
|
154
|
+
* Create a successful phase output with rendered ViewState and carry-forward data.
|
|
155
|
+
*/
|
|
156
|
+
declare function phaseOutput<ViewState extends object, CarryForward = {}>(rendered: ViewState, carryForward: CarryForward): PhaseOutput<ViewState, CarryForward>;
|
|
157
|
+
/**
|
|
158
|
+
* @deprecated Use phaseOutput instead. Kept for backwards compatibility.
|
|
159
|
+
*/
|
|
160
|
+
declare function partialRender<ViewState extends object, CarryForward>(rendered: ViewState, carryForward: CarryForward): PhaseOutput<ViewState, CarryForward>;
|
|
78
161
|
|
|
79
162
|
type BuilderStates = 'Props' | 'Services' | 'Contexts' | 'UrlLoader' | 'SlowlyRender' | 'FastRender' | 'InteractiveRender' | 'Done';
|
|
80
163
|
type Signals<T extends object> = {
|
|
@@ -91,7 +174,8 @@ type Builder<State extends BuilderStates, Refs extends object, SlowVS extends ob
|
|
|
91
174
|
...Services
|
|
92
175
|
], Contexts, PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
93
176
|
withFastRender<NewCarryForward extends object>(fastRender: RenderFast<Services, PropsT, FastVS, NewCarryForward>): Builder<'InteractiveRender', Refs, SlowVS, FastVS, InteractiveVS, Services, [
|
|
94
|
-
Signals<
|
|
177
|
+
Signals<FastVS>,
|
|
178
|
+
NewCarryForward,
|
|
95
179
|
...Contexts
|
|
96
180
|
], PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
97
181
|
withInteractive(comp: ComponentConstructor<PropsT, Refs, InteractiveVS, Contexts, CompCore>): Builder<'Done', Refs, SlowVS, FastVS, InteractiveVS, Services, Contexts, PropsT, Params, CompCore>;
|
|
@@ -103,7 +187,8 @@ type Builder<State extends BuilderStates, Refs extends object, SlowVS extends ob
|
|
|
103
187
|
...Services
|
|
104
188
|
], Contexts, PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
105
189
|
withFastRender<NewCarryForward extends object>(fastRender: RenderFast<Services, PropsT, FastVS, NewCarryForward>): Builder<'InteractiveRender', Refs, SlowVS, FastVS, InteractiveVS, Services, [
|
|
106
|
-
Signals<
|
|
190
|
+
Signals<FastVS>,
|
|
191
|
+
NewCarryForward,
|
|
107
192
|
...Contexts
|
|
108
193
|
], PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
109
194
|
withInteractive(comp: ComponentConstructor<PropsT, Refs, InteractiveVS, Contexts, CompCore>): Builder<'Done', Refs, SlowVS, FastVS, InteractiveVS, Services, Contexts, PropsT, Params, CompCore>;
|
|
@@ -114,7 +199,8 @@ type Builder<State extends BuilderStates, Refs extends object, SlowVS extends ob
|
|
|
114
199
|
...Services
|
|
115
200
|
], Contexts, PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
116
201
|
withFastRender<NewCarryForward extends object>(fastRender: RenderFast<Services, PropsT, FastVS, NewCarryForward>): Builder<'InteractiveRender', Refs, SlowVS, FastVS, InteractiveVS, Services, [
|
|
117
|
-
Signals<
|
|
202
|
+
Signals<FastVS>,
|
|
203
|
+
NewCarryForward,
|
|
118
204
|
...Contexts
|
|
119
205
|
], PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
120
206
|
withInteractive(comp: ComponentConstructor<PropsT, Refs, InteractiveVS, Contexts, CompCore>): Builder<'Done', Refs, SlowVS, FastVS, InteractiveVS, Services, Contexts, PropsT, Params, CompCore>;
|
|
@@ -124,13 +210,15 @@ type Builder<State extends BuilderStates, Refs extends object, SlowVS extends ob
|
|
|
124
210
|
...Services
|
|
125
211
|
], Contexts, PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
126
212
|
withFastRender<NewCarryForward extends object>(fastRender: RenderFast<Services, PropsT, FastVS, NewCarryForward>): Builder<'InteractiveRender', Refs, SlowVS, FastVS, InteractiveVS, Services, [
|
|
127
|
-
Signals<
|
|
213
|
+
Signals<FastVS>,
|
|
214
|
+
NewCarryForward,
|
|
128
215
|
...Contexts
|
|
129
216
|
], PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
130
217
|
withInteractive(comp: ComponentConstructor<PropsT, Refs, InteractiveVS, Contexts, CompCore>): Builder<'Done', Refs, SlowVS, FastVS, InteractiveVS, Services, Contexts, PropsT, Params, CompCore>;
|
|
131
218
|
} : State extends 'FastRender' ? JayStackComponentDefinition<Refs, SlowVS, FastVS, InteractiveVS, Services, Contexts, PropsT, Params, CompCore> & {
|
|
132
219
|
withFastRender<NewCarryForward extends object>(fastRender: RenderFast<Services, PropsT, FastVS, NewCarryForward>): Builder<'InteractiveRender', Refs, SlowVS, FastVS, InteractiveVS, Services, [
|
|
133
|
-
Signals<
|
|
220
|
+
Signals<FastVS>,
|
|
221
|
+
NewCarryForward,
|
|
134
222
|
...Contexts
|
|
135
223
|
], PropsT, Params, JayComponentCore<PropsT, InteractiveVS>>;
|
|
136
224
|
withInteractive(comp: ComponentConstructor<PropsT, Refs, InteractiveVS, Contexts, CompCore>): Builder<'Done', Refs, SlowVS, FastVS, InteractiveVS, Services, Contexts, PropsT, Params, CompCore>;
|
|
@@ -159,4 +247,369 @@ declare function makeJayStackComponent<Render extends JayContract<any, any, any,
|
|
|
159
247
|
], [
|
|
160
248
|
], {}, {}, JayComponentCore<object, ExtractInteractiveViewState<Render>>>;
|
|
161
249
|
|
|
162
|
-
|
|
250
|
+
/**
|
|
251
|
+
* Builder interface for contract generators without services
|
|
252
|
+
*/
|
|
253
|
+
interface ContractGeneratorBuilderInitial {
|
|
254
|
+
/**
|
|
255
|
+
* Adds service dependencies to the contract generator.
|
|
256
|
+
* Services will be injected when generateWith() is called.
|
|
257
|
+
*/
|
|
258
|
+
withServices<Services extends Array<any>>(...serviceMarkers: ServiceMarkers<Services>): ContractGeneratorBuilderWithServices<Services>;
|
|
259
|
+
/**
|
|
260
|
+
* Defines the contract generation function without services.
|
|
261
|
+
*/
|
|
262
|
+
generateWith(fn: () => Promise<GeneratedContractYaml[]> | GeneratedContractYaml[]): DynamicContractGenerator<[]>;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Builder interface for contract generators with services
|
|
266
|
+
*/
|
|
267
|
+
interface ContractGeneratorBuilderWithServices<Services extends Array<any>> {
|
|
268
|
+
/**
|
|
269
|
+
* Defines the contract generation function with service injection.
|
|
270
|
+
* Services are provided as parameters based on the order specified in withServices().
|
|
271
|
+
*/
|
|
272
|
+
generateWith(fn: ContractGeneratorFunction<Services>): DynamicContractGenerator<Services>;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Creates a new contract generator builder.
|
|
276
|
+
*
|
|
277
|
+
* @returns A builder for creating dynamic contract generators
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```typescript
|
|
281
|
+
* // Without services
|
|
282
|
+
* export const generator = makeContractGenerator()
|
|
283
|
+
* .generateWith(async () => {
|
|
284
|
+
* return [
|
|
285
|
+
* { name: 'Contract1', yaml: 'name: Contract1\ntags: [...]' },
|
|
286
|
+
* { name: 'Contract2', yaml: 'name: Contract2\ntags: [...]' }
|
|
287
|
+
* ];
|
|
288
|
+
* });
|
|
289
|
+
*
|
|
290
|
+
* // With services
|
|
291
|
+
* export const generator = makeContractGenerator()
|
|
292
|
+
* .withServices(CMS_SERVICE, API_SERVICE)
|
|
293
|
+
* .generateWith(async (cms, api) => {
|
|
294
|
+
* const data = await cms.fetch();
|
|
295
|
+
* return data.map(item => ({
|
|
296
|
+
* name: item.name,
|
|
297
|
+
* yaml: generateYaml(item)
|
|
298
|
+
* }));
|
|
299
|
+
* });
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
declare function makeContractGenerator(): ContractGeneratorBuilderInitial;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Factory object returned by RenderPipeline.for<VS, CF>().
|
|
306
|
+
* Provides entry points to create a typed pipeline.
|
|
307
|
+
*/
|
|
308
|
+
interface PipelineFactory<TargetVS extends object, TargetCF extends object> {
|
|
309
|
+
/** Start with a success value (can be T or Promise<T>) */
|
|
310
|
+
ok<T>(value: T | Promise<T>): RenderPipeline<T, TargetVS, TargetCF>;
|
|
311
|
+
/**
|
|
312
|
+
* Start with a function that returns T or Promise<T>.
|
|
313
|
+
* Catches errors into the pipeline (accessible via recover()).
|
|
314
|
+
*/
|
|
315
|
+
try<T>(fn: () => T | Promise<T>): RenderPipeline<T, TargetVS, TargetCF>;
|
|
316
|
+
/** Start from an existing outcome */
|
|
317
|
+
from<T extends object>(outcome: RenderOutcome<T, unknown>): RenderPipeline<T, TargetVS, TargetCF>;
|
|
318
|
+
notFound(message?: string, details?: Record<string, unknown>): RenderPipeline<never, TargetVS, TargetCF>;
|
|
319
|
+
badRequest(message?: string, details?: Record<string, unknown>): RenderPipeline<never, TargetVS, TargetCF>;
|
|
320
|
+
unauthorized(message?: string, details?: Record<string, unknown>): RenderPipeline<never, TargetVS, TargetCF>;
|
|
321
|
+
forbidden(message?: string, details?: Record<string, unknown>): RenderPipeline<never, TargetVS, TargetCF>;
|
|
322
|
+
serverError(status: number, message?: string, details?: Record<string, unknown>): RenderPipeline<never, TargetVS, TargetCF>;
|
|
323
|
+
clientError(status: number, message?: string, details?: Record<string, unknown>): RenderPipeline<never, TargetVS, TargetCF>;
|
|
324
|
+
redirect(status: number, location: string): RenderPipeline<never, TargetVS, TargetCF>;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* A pipeline for composing render operations with automatic error propagation.
|
|
328
|
+
*
|
|
329
|
+
* Type Parameters:
|
|
330
|
+
* - T: The current working value being transformed through the chain
|
|
331
|
+
* - TargetVS: The expected ViewState output type (set via .for<>())
|
|
332
|
+
* - TargetCF: The expected CarryForward output type (set via .for<>())
|
|
333
|
+
*
|
|
334
|
+
* Usage:
|
|
335
|
+
* ```typescript
|
|
336
|
+
* const Pipeline = RenderPipeline.for<SlowViewState, CarryForward>();
|
|
337
|
+
*
|
|
338
|
+
* return Pipeline
|
|
339
|
+
* .try(() => fetchData())
|
|
340
|
+
* .map(data => data ? data : Pipeline.notFound())
|
|
341
|
+
* .map(async data => enrichData(data))
|
|
342
|
+
* .toPhaseOutput(data => ({
|
|
343
|
+
* viewState: { ... },
|
|
344
|
+
* carryForward: { ... }
|
|
345
|
+
* }));
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
declare class RenderPipeline<T, TargetVS extends object = object, TargetCF extends object = Record<string, never>> {
|
|
349
|
+
private readonly _value;
|
|
350
|
+
private readonly _isSuccess;
|
|
351
|
+
private constructor();
|
|
352
|
+
/**
|
|
353
|
+
* Create a typed pipeline factory with target output types declared upfront.
|
|
354
|
+
* TypeScript validates that .toPhaseOutput() produces these types.
|
|
355
|
+
*/
|
|
356
|
+
static for<TargetVS extends object, TargetCF extends object = Record<string, never>>(): PipelineFactory<TargetVS, TargetCF>;
|
|
357
|
+
/**
|
|
358
|
+
* Transform the working value. Always returns RenderPipeline (sync).
|
|
359
|
+
*
|
|
360
|
+
* The mapping function can return:
|
|
361
|
+
* - U: Plain value
|
|
362
|
+
* - Promise<U>: Async value (resolved at toPhaseOutput)
|
|
363
|
+
* - RenderPipeline<U>: For conditional errors/branching
|
|
364
|
+
*
|
|
365
|
+
* Errors pass through unchanged.
|
|
366
|
+
*/
|
|
367
|
+
map<U>(fn: (value: T) => U | Promise<U> | RenderPipeline<U, TargetVS, TargetCF>): RenderPipeline<U, TargetVS, TargetCF>;
|
|
368
|
+
/**
|
|
369
|
+
* Handle errors, potentially recovering to a success.
|
|
370
|
+
* The function receives the caught Error and can return a new pipeline.
|
|
371
|
+
*/
|
|
372
|
+
recover<U>(fn: (error: Error) => RenderPipeline<U, TargetVS, TargetCF>): RenderPipeline<T | U, TargetVS, TargetCF>;
|
|
373
|
+
/**
|
|
374
|
+
* Convert to final PhaseOutput. This is the ONLY async method.
|
|
375
|
+
* Resolves all pending promises and applies the final mapping.
|
|
376
|
+
*/
|
|
377
|
+
toPhaseOutput(fn: (value: T) => {
|
|
378
|
+
viewState: TargetVS;
|
|
379
|
+
carryForward: TargetCF;
|
|
380
|
+
}): Promise<RenderOutcome<TargetVS, TargetCF>>;
|
|
381
|
+
/** Check if this pipeline is in a success state */
|
|
382
|
+
isOk(): boolean;
|
|
383
|
+
/** Check if this pipeline is in an error state */
|
|
384
|
+
isError(): boolean;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Supported HTTP methods for actions and queries.
|
|
389
|
+
*/
|
|
390
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
391
|
+
/**
|
|
392
|
+
* Cache options for GET requests.
|
|
393
|
+
*/
|
|
394
|
+
interface CacheOptions {
|
|
395
|
+
/** Cache duration in seconds */
|
|
396
|
+
maxAge?: number;
|
|
397
|
+
/** Time in seconds to serve stale content while revalidating */
|
|
398
|
+
staleWhileRevalidate?: number;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Error class for action/query failures.
|
|
402
|
+
* Thrown from action handlers to indicate business logic errors.
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* ```typescript
|
|
406
|
+
* throw new ActionError('NOT_AVAILABLE', 'Only 2 units available');
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
declare class ActionError extends Error {
|
|
410
|
+
readonly code: string;
|
|
411
|
+
readonly name = "ActionError";
|
|
412
|
+
constructor(code: string, message: string);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* A callable action/query that makes an HTTP request to the server.
|
|
416
|
+
* This is the final type returned by the builder's withHandler() method.
|
|
417
|
+
*/
|
|
418
|
+
interface JayAction<Input, Output> {
|
|
419
|
+
/** Call the action - makes HTTP request to server */
|
|
420
|
+
(input: Input): Promise<Output>;
|
|
421
|
+
/** Unique action name for routing */
|
|
422
|
+
readonly actionName: string;
|
|
423
|
+
/** HTTP method (GET, POST, etc.) */
|
|
424
|
+
readonly method: HttpMethod;
|
|
425
|
+
/** Internal marker for type identification */
|
|
426
|
+
readonly _brand: 'JayAction';
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Internal action definition used for server-side registration.
|
|
430
|
+
* Contains all metadata and the handler function.
|
|
431
|
+
*/
|
|
432
|
+
interface JayActionDefinition<Input, Output, Services extends any[]> {
|
|
433
|
+
/** Unique action name */
|
|
434
|
+
actionName: string;
|
|
435
|
+
/** HTTP method */
|
|
436
|
+
method: HttpMethod;
|
|
437
|
+
/** Cache options (for GET requests) */
|
|
438
|
+
cacheOptions?: CacheOptions;
|
|
439
|
+
/** Service markers for dependency injection */
|
|
440
|
+
services: ServiceMarkers<Services>;
|
|
441
|
+
/** The handler function */
|
|
442
|
+
handler: (input: Input, ...services: Services) => Promise<Output>;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Builder interface for creating type-safe actions/queries.
|
|
446
|
+
*/
|
|
447
|
+
interface JayActionBuilder<Services extends any[], Input, Output, DefaultMethod extends HttpMethod> {
|
|
448
|
+
/**
|
|
449
|
+
* Specify services to inject into the handler.
|
|
450
|
+
*/
|
|
451
|
+
withServices<NewServices extends any[]>(...services: ServiceMarkers<NewServices>): JayActionBuilder<NewServices, Input, Output, DefaultMethod>;
|
|
452
|
+
/**
|
|
453
|
+
* Override the HTTP method.
|
|
454
|
+
*/
|
|
455
|
+
withMethod<M extends HttpMethod>(method: M): JayActionBuilder<Services, Input, Output, M>;
|
|
456
|
+
/**
|
|
457
|
+
* Enable caching (typically for GET requests).
|
|
458
|
+
*/
|
|
459
|
+
withCaching(options?: CacheOptions): JayActionBuilder<Services, Input, Output, DefaultMethod>;
|
|
460
|
+
/**
|
|
461
|
+
* Define the handler function. Input and output types are inferred from the handler signature.
|
|
462
|
+
*/
|
|
463
|
+
withHandler<I, O>(handler: (input: I, ...services: Services) => Promise<O>): JayAction<I, O> & JayActionDefinition<I, O, Services>;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Create an action (defaults to POST method).
|
|
467
|
+
* Use for mutations: add to cart, submit form, update profile, etc.
|
|
468
|
+
*
|
|
469
|
+
* @param name - Unique action name (e.g., 'cart.addToCart')
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* ```typescript
|
|
473
|
+
* export const addToCart = makeJayAction('cart.addToCart')
|
|
474
|
+
* .withServices(CART_SERVICE)
|
|
475
|
+
* .withHandler(async (input: { productId: string; quantity: number }, cartService) => {
|
|
476
|
+
* const cart = await cartService.addItem(input.productId, input.quantity);
|
|
477
|
+
* return { cartItemCount: cart.items.length };
|
|
478
|
+
* });
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
declare function makeJayAction(name: string): JayActionBuilder<[], unknown, unknown, 'POST'>;
|
|
482
|
+
/**
|
|
483
|
+
* Create a query (defaults to GET method).
|
|
484
|
+
* Use for reads: search, get details, list items, etc.
|
|
485
|
+
* GET enables browser/CDN caching.
|
|
486
|
+
*
|
|
487
|
+
* @param name - Unique query name (e.g., 'products.search')
|
|
488
|
+
*
|
|
489
|
+
* @example
|
|
490
|
+
* ```typescript
|
|
491
|
+
* export const searchProducts = makeJayQuery('products.search')
|
|
492
|
+
* .withServices(PRODUCTS_DATABASE_SERVICE)
|
|
493
|
+
* .withCaching({ maxAge: 60 })
|
|
494
|
+
* .withHandler(async (input: { query: string }, productsDb) => {
|
|
495
|
+
* return productsDb.search(input.query);
|
|
496
|
+
* });
|
|
497
|
+
* ```
|
|
498
|
+
*/
|
|
499
|
+
declare function makeJayQuery(name: string): JayActionBuilder<[], unknown, unknown, 'GET'>;
|
|
500
|
+
/**
|
|
501
|
+
* Extract the input type from a JayAction.
|
|
502
|
+
*/
|
|
503
|
+
type ActionInput<T> = T extends JayAction<infer I, any> ? I : never;
|
|
504
|
+
/**
|
|
505
|
+
* Extract the output type from a JayAction.
|
|
506
|
+
*/
|
|
507
|
+
type ActionOutput<T> = T extends JayAction<any, infer O> ? O : never;
|
|
508
|
+
/**
|
|
509
|
+
* Check if a value is a JayAction.
|
|
510
|
+
*/
|
|
511
|
+
declare function isJayAction(value: unknown): value is JayAction<unknown, unknown>;
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Builder for plugin/project initialization with type-safe server-to-client data flow.
|
|
515
|
+
*
|
|
516
|
+
* Usage:
|
|
517
|
+
* ```typescript
|
|
518
|
+
* export const init = makeJayInit()
|
|
519
|
+
* .withServer(async () => {
|
|
520
|
+
* registerService(MY_SERVICE, createService());
|
|
521
|
+
* return { apiUrl: config.url };
|
|
522
|
+
* })
|
|
523
|
+
* .withClient((data) => {
|
|
524
|
+
* // data is typed from withServer return!
|
|
525
|
+
* registerGlobalContext(MY_CONFIG_CONTEXT, data);
|
|
526
|
+
* });
|
|
527
|
+
* ```
|
|
528
|
+
*/
|
|
529
|
+
/**
|
|
530
|
+
* The compiled init object that contains server and/or client init functions.
|
|
531
|
+
* The compiler transforms the builder chain into this object.
|
|
532
|
+
*/
|
|
533
|
+
interface JayInit<T = void> {
|
|
534
|
+
readonly __brand: 'JayInit';
|
|
535
|
+
/** Key for namespacing (plugin name or 'project'). Filled in by framework. */
|
|
536
|
+
readonly key: string;
|
|
537
|
+
/** Server init function. Returns data to pass to client. */
|
|
538
|
+
readonly _serverInit?: () => T | Promise<T>;
|
|
539
|
+
/** Client init function. Receives data from server. */
|
|
540
|
+
readonly _clientInit?: (data: T) => void | Promise<void>;
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Builder interface for constructing a JayInit.
|
|
544
|
+
*/
|
|
545
|
+
interface JayInitBuilder<T = void> {
|
|
546
|
+
/**
|
|
547
|
+
* Defines server-side initialization logic.
|
|
548
|
+
* The return value is passed to the client init function.
|
|
549
|
+
*
|
|
550
|
+
* @param callback - Async function that runs on server startup
|
|
551
|
+
* @returns Builder with client data type set to callback's return type
|
|
552
|
+
*/
|
|
553
|
+
withServer<R extends Record<string, any>>(callback: () => R | Promise<R>): JayInitBuilderWithServer<R>;
|
|
554
|
+
/**
|
|
555
|
+
* Defines client-side initialization logic (when no server data needed).
|
|
556
|
+
*
|
|
557
|
+
* @param callback - Function that runs on client before component tree mounts
|
|
558
|
+
* @returns The final JayInit object
|
|
559
|
+
*/
|
|
560
|
+
withClient(callback: () => void | Promise<void>): JayInit<void>;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Builder after withServer has been called.
|
|
564
|
+
*/
|
|
565
|
+
interface JayInitBuilderWithServer<T extends Record<string, any>> extends JayInit<T> {
|
|
566
|
+
/**
|
|
567
|
+
* Defines client-side initialization logic with server data.
|
|
568
|
+
*
|
|
569
|
+
* @param callback - Function that receives data from server init
|
|
570
|
+
* @returns The final JayInit object
|
|
571
|
+
*/
|
|
572
|
+
withClient(callback: (data: T) => void | Promise<void>): JayInit<T>;
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Creates a builder for plugin/project initialization.
|
|
576
|
+
*
|
|
577
|
+
* The key parameter is optional:
|
|
578
|
+
* - For plugins: defaults to plugin name from plugin.yaml (injected by framework)
|
|
579
|
+
* - For project: defaults to 'project'
|
|
580
|
+
*
|
|
581
|
+
* @param key - Optional namespace key (typically omitted)
|
|
582
|
+
* @returns A builder to define server and client initialization
|
|
583
|
+
*
|
|
584
|
+
* @example
|
|
585
|
+
* ```typescript
|
|
586
|
+
* // Plugin init (key defaults to plugin name)
|
|
587
|
+
* export const init = makeJayInit()
|
|
588
|
+
* .withServer(async () => {
|
|
589
|
+
* registerService(STORES_SERVICE, createService());
|
|
590
|
+
* return { currency: 'USD', enableCart: true };
|
|
591
|
+
* })
|
|
592
|
+
* .withClient((data) => {
|
|
593
|
+
* registerGlobalContext(STORES_CONFIG, data);
|
|
594
|
+
* });
|
|
595
|
+
*
|
|
596
|
+
* // Server-only init
|
|
597
|
+
* export const init = makeJayInit()
|
|
598
|
+
* .withServer(async () => {
|
|
599
|
+
* registerService(DB_SERVICE, await connectDb());
|
|
600
|
+
* });
|
|
601
|
+
*
|
|
602
|
+
* // Client-only init
|
|
603
|
+
* export const init = makeJayInit()
|
|
604
|
+
* .withClient(() => {
|
|
605
|
+
* initAnalytics();
|
|
606
|
+
* });
|
|
607
|
+
* ```
|
|
608
|
+
*/
|
|
609
|
+
declare function makeJayInit(key?: string): JayInitBuilder<void>;
|
|
610
|
+
/**
|
|
611
|
+
* Type guard to check if an object is a JayInit.
|
|
612
|
+
*/
|
|
613
|
+
declare function isJayInit(obj: unknown): obj is JayInit<any>;
|
|
614
|
+
|
|
615
|
+
export { ActionError, type ActionInput, type ActionOutput, type AnyFastRenderResult, type AnyJayStackComponentDefinition, type AnySlowlyRenderResult, type Builder, type CacheOptions, type ClientError4xx, type ContractGeneratorFunction, DYNAMIC_CONTRACT_SERVICE, type DynamicContractGenerator, type DynamicContractMetadata, type FastRenderResult, type GeneratedContractYaml, type HttpMethod, type JayAction, type JayActionBuilder, type JayActionDefinition, type JayInit, type JayInitBuilder, type JayInitBuilderWithServer, type JayStackComponentDefinition, type LoadParams, type PageProps, type PartialRender, type PhaseOutput, type PipelineFactory, type Redirect3xx, type RenderFast, type RenderOutcome, RenderPipeline, type RenderSlowly, type ServerError5xx, type ServiceInstances, type ServiceMarker, type ServiceMarkers, type Signals, type SlowlyRenderResult, type UrlParams, badRequest, clientError4xx, createJayService, forbidden, isJayAction, isJayInit, makeContractGenerator, makeJayAction, makeJayInit, makeJayQuery, makeJayStackComponent, notFound, partialRender, phaseOutput, redirect3xx, serverError5xx, unauthorized };
|