@jay-framework/fullstack-component 0.9.0 → 0.11.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/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: 'redirect';
78
+ kind: 'Redirect';
48
79
  status: number;
49
80
  location: string;
81
+ message?: string;
50
82
  }
51
- interface PartialRender<ViewState extends object, CarryForward> {
52
- kind: 'PartialRender';
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
- type SlowlyRenderResult<ViewState extends object, CarryForward> = PartialRender<ViewState, CarryForward> | ServerError5xx | ClientError4xx | Redirect3xx;
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> = PartialRender<ViewState, CarryForward> | ServerError5xx | ClientError4xx | Redirect3xx;
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 redirect3xx(status: number, location: string): Redirect3xx;
77
- declare function partialRender<ViewState extends object, CarryForward>(rendered: ViewState, carryForward: CarryForward): PartialRender<ViewState, CarryForward>;
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<NewCarryForward>,
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<NewCarryForward>,
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<NewCarryForward>,
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<NewCarryForward>,
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<NewCarryForward>,
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
- export { type AnyFastRenderResult, type AnyJayStackComponentDefinition, type AnySlowlyRenderResult, type Builder, type ClientError4xx, type FastRenderResult, type JayStackComponentDefinition, type LoadParams, type PageProps, type PartialRender, type Redirect3xx, type RenderFast, type RenderSlowly, type ServerError5xx, type ServiceMarker, type ServiceMarkers, type Signals, type SlowlyRenderResult, type UrlParams, clientError4xx, createJayService, makeJayStackComponent, notFound, partialRender, redirect3xx, serverError5xx };
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 };