fraiseql 2.1.1

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.
@@ -0,0 +1,1688 @@
1
+ /**
2
+ * Type mapping and introspection for GraphQL schema generation.
3
+ *
4
+ * This module converts TypeScript type annotations to GraphQL type strings,
5
+ * enabling compile-time schema generation without runtime overhead.
6
+ */
7
+ /**
8
+ * Convert TypeScript type to GraphQL type string.
9
+ *
10
+ * @param type - TypeScript type annotation
11
+ * @returns Tuple of [graphql_type, is_nullable]
12
+ *
13
+ * @example
14
+ * typeToGraphQL(String) => ["String", false]
15
+ * typeToGraphQL(String | null) => ["String", true]
16
+ * typeToGraphQL(Array<User>) => ["[User!]", false]
17
+ */
18
+ declare function typeToGraphQL(type: unknown): [graphqlType: string, nullable: boolean];
19
+ /**
20
+ * Field information extracted from a class with type metadata.
21
+ */
22
+ interface FieldInfo {
23
+ type: string;
24
+ nullable: boolean;
25
+ }
26
+ /**
27
+ * Extract field information from class property metadata.
28
+ *
29
+ * @param fields - Dictionary mapping field names to type annotations
30
+ * @returns Dictionary of field_name -> FieldInfo
31
+ *
32
+ * @example
33
+ * const fields = {
34
+ * id: "number",
35
+ * name: "string",
36
+ * email: "string | null"
37
+ * };
38
+ * extractFieldInfo(fields) => {
39
+ * id: { type: "Int", nullable: false },
40
+ * name: { type: "String", nullable: false },
41
+ * email: { type: "String", nullable: true }
42
+ * }
43
+ */
44
+ declare function extractFieldInfo(fields: Record<string, unknown>): Record<string, FieldInfo>;
45
+ /**
46
+ * Argument information for a function parameter.
47
+ */
48
+ interface ArgumentInfo {
49
+ name: string;
50
+ type: string;
51
+ nullable: boolean;
52
+ default?: unknown;
53
+ }
54
+ /**
55
+ * Return type information for a function.
56
+ */
57
+ interface ReturnTypeInfo {
58
+ type: string;
59
+ nullable: boolean;
60
+ isList: boolean;
61
+ }
62
+ /**
63
+ * Function signature information extracted from a decorated function.
64
+ */
65
+ interface FunctionSignature {
66
+ arguments: ArgumentInfo[];
67
+ returnType: ReturnTypeInfo;
68
+ }
69
+ /**
70
+ * Extract GraphQL-relevant information from function signature.
71
+ *
72
+ * @param name - Function name
73
+ * @param params - Dictionary mapping parameter names to type annotations
74
+ * @param returnType - Return type annotation
75
+ * @returns FunctionSignature with arguments and return type info
76
+ *
77
+ * @example
78
+ * extractFunctionSignature(
79
+ * "users",
80
+ * { limit: "number", offset: "number" },
81
+ * "User[]"
82
+ * ) => {
83
+ * arguments: [
84
+ * { name: "limit", type: "Int", nullable: false },
85
+ * { name: "offset", type: "Int", nullable: false }
86
+ * ],
87
+ * returnType: { type: "[User!]", nullable: false, isList: true }
88
+ * }
89
+ */
90
+ declare function extractFunctionSignature(_name: string, params: Record<string, unknown>, returnType: unknown): FunctionSignature;
91
+
92
+ /**
93
+ * FraiseQL scalar type markers for schema authoring.
94
+ *
95
+ * These are branded type aliases used in TypeScript to generate the correct
96
+ * GraphQL scalar types in schema.json. They have no runtime behavior - validation
97
+ * and serialization happen in the Rust runtime after compilation.
98
+ *
99
+ * Architecture:
100
+ * TypeScript type annotation → schema.json type string → Rust FieldType → codegen/introspection
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * import { Type } from "fraiseql";
105
+ * import { ID, DateTime, Email, URL } from "fraiseql/scalars";
106
+ *
107
+ * @Type()
108
+ * class User {
109
+ * id: ID; // → "ID" in schema.json → FieldType::Id
110
+ * name: string; // → "String"
111
+ * email: Email; // → "Email" → FieldType::Scalar("Email")
112
+ * website: URL | null; // → "URL" (nullable)
113
+ * createdAt: DateTime; // → "DateTime" → FieldType::DateTime
114
+ * }
115
+ * ```
116
+ *
117
+ * FraiseQL Convention:
118
+ * - `id` fields should ALWAYS use `ID` type (UUID v4 at runtime)
119
+ * - Foreign keys (e.g., `authorId`) should also use `ID`
120
+ *
121
+ * Custom Scalars:
122
+ * You can define your own custom scalars using branded types:
123
+ *
124
+ * ```typescript
125
+ * type MyCustomScalar = string & { readonly __brand: "MyCustomScalar" };
126
+ * ```
127
+ *
128
+ * The scalar name will pass through to schema.json and be validated at runtime.
129
+ *
130
+ * @packageDocumentation
131
+ */
132
+ /**
133
+ * Abstract base class for custom GraphQL scalars with validation.
134
+ *
135
+ * Subclasses must define a `name` property and implement
136
+ * the three validation methods (serialize, parseValue, parseLiteral).
137
+ *
138
+ * Use with the @Scalar decorator to register custom scalars with the schema.
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * class Email extends CustomScalar {
143
+ * name = "Email"
144
+ *
145
+ * serialize(value: unknown): string {
146
+ * return String(value)
147
+ * }
148
+ *
149
+ * parseValue(value: unknown): string {
150
+ * const str = String(value)
151
+ * if (!str.includes("@")) {
152
+ * throw new Error("Invalid email address")
153
+ * }
154
+ * return str
155
+ * }
156
+ *
157
+ * parseLiteral(ast: unknown): string {
158
+ * if (ast && typeof ast === "object" && "value" in ast) {
159
+ * return this.parseValue((ast as any).value)
160
+ * }
161
+ * throw new Error("Invalid email literal")
162
+ * }
163
+ * }
164
+ * ```
165
+ */
166
+ declare abstract class CustomScalar {
167
+ /**
168
+ * Scalar name (e.g., "Email"). Must be unique in schema.
169
+ */
170
+ abstract name: string;
171
+ /**
172
+ * Convert value to output format (schema → response).
173
+ *
174
+ * Called when serializing a field value in GraphQL response.
175
+ *
176
+ * @param value - The internal representation (from database/object)
177
+ * @returns The value formatted for GraphQL response (usually string)
178
+ * @throws If value cannot be serialized
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * serialize(value: Date): string {
183
+ * return value.toISOString()
184
+ * }
185
+ * ```
186
+ */
187
+ abstract serialize(value: unknown): unknown;
188
+ /**
189
+ * Validate and convert input value (client input → internal).
190
+ *
191
+ * Called when a scalar is passed as a variable in GraphQL query.
192
+ *
193
+ * @param value - Raw input value from client
194
+ * @returns Validated/converted value
195
+ * @throws If validation fails
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * parseValue(value: unknown): string {
200
+ * const str = String(value)
201
+ * if (!str.includes("@")) {
202
+ * throw new Error("Invalid email address")
203
+ * }
204
+ * return str
205
+ * }
206
+ * ```
207
+ */
208
+ abstract parseValue(value: unknown): unknown;
209
+ /**
210
+ * Parse GraphQL literal (hardcoded value in query).
211
+ *
212
+ * Called when a scalar is hardcoded in the GraphQL query string
213
+ * (not as a variable).
214
+ *
215
+ * @param ast - GraphQL AST node representing the literal
216
+ * @returns Validated/converted value
217
+ * @throws If literal cannot be parsed
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * parseLiteral(ast: unknown): string {
222
+ * if (ast && typeof ast === "object" && "value" in ast) {
223
+ * return this.parseValue((ast as any).value)
224
+ * }
225
+ * throw new Error(`Invalid email literal: ${ast}`)
226
+ * }
227
+ * ```
228
+ */
229
+ abstract parseLiteral(ast: unknown): unknown;
230
+ }
231
+ /**
232
+ * Creates a branded type for nominal typing.
233
+ * This allows TypeScript to distinguish between different scalar types at compile time.
234
+ */
235
+ type Brand<T, B extends string> = T & {
236
+ readonly __brand: B;
237
+ };
238
+ /**
239
+ * GraphQL ID scalar - used for unique identifiers.
240
+ *
241
+ * FraiseQL enforces UUID v4 format for all ID fields at runtime.
242
+ * This is the REQUIRED type for `id` fields and foreign key references.
243
+ */
244
+ type ID = Brand<string, "ID">;
245
+ /** ISO 8601 DateTime scalar (e.g., "2025-01-10T12:00:00Z"). */
246
+ type DateTime = Brand<string, "DateTime">;
247
+ /** ISO 8601 Date scalar (e.g., "2025-01-10"). */
248
+ type Date = Brand<string, "Date">;
249
+ /** ISO 8601 Time scalar (e.g., "12:00:00"). */
250
+ type Time = Brand<string, "Time">;
251
+ /** Date range scalar (e.g., "[2025-01-01,2025-12-31)"). */
252
+ type DateRange = Brand<string, "DateRange">;
253
+ /** ISO 8601 Duration scalar (e.g., "P1Y2M3D"). */
254
+ type Duration = Brand<string, "Duration">;
255
+ /** Arbitrary JSON value scalar. Maps to PostgreSQL JSONB. */
256
+ type Json = Brand<unknown, "Json">;
257
+ /** UUID scalar (explicit UUID type, distinct from ID). */
258
+ type UUID = Brand<string, "UUID">;
259
+ /** Decimal/BigDecimal scalar for precise numeric values. */
260
+ type Decimal = Brand<string, "Decimal">;
261
+ /** Vector scalar for pgvector embeddings. */
262
+ type Vector = Brand<number[], "Vector">;
263
+ /** Email address scalar with RFC 5322 validation. */
264
+ type Email = Brand<string, "Email">;
265
+ /** Phone number scalar (E.164 format recommended). */
266
+ type PhoneNumber = Brand<string, "PhoneNumber">;
267
+ /** URL scalar with RFC 3986 validation. */
268
+ type URL = Brand<string, "URL">;
269
+ /** Domain name scalar. */
270
+ type DomainName = Brand<string, "DomainName">;
271
+ /** Hostname scalar. */
272
+ type Hostname = Brand<string, "Hostname">;
273
+ /** Postal/ZIP code scalar. */
274
+ type PostalCode = Brand<string, "PostalCode">;
275
+ /** Latitude coordinate (-90 to 90). */
276
+ type Latitude = Brand<number, "Latitude">;
277
+ /** Longitude coordinate (-180 to 180). */
278
+ type Longitude = Brand<number, "Longitude">;
279
+ /** Geographic coordinates scalar (lat,lng or GeoJSON). */
280
+ type Coordinates = Brand<string, "Coordinates">;
281
+ /** IANA timezone identifier (e.g., "America/New_York"). */
282
+ type Timezone = Brand<string, "Timezone">;
283
+ /** Locale code scalar (e.g., "en-US"). */
284
+ type LocaleCode = Brand<string, "LocaleCode">;
285
+ /** ISO 639-1 language code (e.g., "en"). */
286
+ type LanguageCode = Brand<string, "LanguageCode">;
287
+ /** ISO 3166-1 alpha-2 country code (e.g., "US"). */
288
+ type CountryCode = Brand<string, "CountryCode">;
289
+ /** International Bank Account Number. */
290
+ type IBAN = Brand<string, "IBAN">;
291
+ /** CUSIP identifier for North American securities. */
292
+ type CUSIP = Brand<string, "CUSIP">;
293
+ /** International Securities Identification Number. */
294
+ type ISIN = Brand<string, "ISIN">;
295
+ /** Stock Exchange Daily Official List number. */
296
+ type SEDOL = Brand<string, "SEDOL">;
297
+ /** Legal Entity Identifier. */
298
+ type LEI = Brand<string, "LEI">;
299
+ /** Market Identifier Code. */
300
+ type MIC = Brand<string, "MIC">;
301
+ /** ISO 4217 currency code (e.g., "USD"). */
302
+ type CurrencyCode = Brand<string, "CurrencyCode">;
303
+ /** Monetary amount with currency (e.g., "USD 100.00"). */
304
+ type Money = Brand<string, "Money">;
305
+ /** Stock exchange code. */
306
+ type ExchangeCode = Brand<string, "ExchangeCode">;
307
+ /** Currency exchange rate. */
308
+ type ExchangeRate = Brand<string, "ExchangeRate">;
309
+ /** Stock ticker symbol. */
310
+ type StockSymbol = Brand<string, "StockSymbol">;
311
+ /** Percentage value (0-100 or 0-1 depending on context). */
312
+ type Percentage = Brand<number, "Percentage">;
313
+ /** URL-safe slug (lowercase, hyphens, no spaces). */
314
+ type Slug = Brand<string, "Slug">;
315
+ /** Semantic version string (e.g., "1.2.3"). */
316
+ type SemanticVersion = Brand<string, "SemanticVersion">;
317
+ /** SHA-256 hash string (64 hex characters). */
318
+ type HashSHA256 = Brand<string, "HashSHA256">;
319
+ /** API key string. */
320
+ type APIKey = Brand<string, "APIKey">;
321
+ /** Vehicle license plate number. */
322
+ type LicensePlate = Brand<string, "LicensePlate">;
323
+ /** Vehicle Identification Number. */
324
+ type VIN = Brand<string, "VIN">;
325
+ /** Shipping tracking number. */
326
+ type TrackingNumber = Brand<string, "TrackingNumber">;
327
+ /** Shipping container number (ISO 6346). */
328
+ type ContainerNumber = Brand<string, "ContainerNumber">;
329
+ /** IP address (IPv4 or IPv6). */
330
+ type IPAddress = Brand<string, "IPAddress">;
331
+ /** IPv4 address. */
332
+ type IPv4 = Brand<string, "IPv4">;
333
+ /** IPv6 address. */
334
+ type IPv6 = Brand<string, "IPv6">;
335
+ /** MAC address. */
336
+ type MACAddress = Brand<string, "MACAddress">;
337
+ /** CIDR notation for IP ranges. */
338
+ type CIDR = Brand<string, "CIDR">;
339
+ /** Network port number (0-65535). */
340
+ type Port = Brand<number, "Port">;
341
+ /** IATA airport code (e.g., "JFK"). */
342
+ type AirportCode = Brand<string, "AirportCode">;
343
+ /** UN/LOCODE port code. */
344
+ type PortCode = Brand<string, "PortCode">;
345
+ /** Flight number (e.g., "AA123"). */
346
+ type FlightNumber = Brand<string, "FlightNumber">;
347
+ /** Markdown-formatted text. */
348
+ type Markdown = Brand<string, "Markdown">;
349
+ /** HTML-formatted text. */
350
+ type HTML = Brand<string, "HTML">;
351
+ /** MIME type (e.g., "application/json"). */
352
+ type MimeType = Brand<string, "MimeType">;
353
+ /** Color value (hex, RGB, or named). */
354
+ type Color = Brand<string, "Color">;
355
+ /** Image reference (URL or base64). */
356
+ type Image = Brand<string, "Image">;
357
+ /** File reference (URL or path). */
358
+ type File = Brand<string, "File">;
359
+ /** PostgreSQL ltree path (e.g., "root.child.leaf"). */
360
+ type LTree = Brand<string, "LTree">;
361
+ /**
362
+ * Set of all known scalar type names.
363
+ * Used by the type system to recognize scalar types.
364
+ */
365
+ declare const SCALAR_NAMES: Set<string>;
366
+ /**
367
+ * Check if a type name is a known scalar type.
368
+ */
369
+ declare function isScalarType(typeName: string): boolean;
370
+
371
+ /**
372
+ * Global schema registry for collecting types, queries, and mutations.
373
+ *
374
+ * This module maintains a singleton registry of all definitions made via decorators,
375
+ * which is then exported to schema.json for compilation.
376
+ */
377
+
378
+ /**
379
+ * Field metadata for access control and deprecation.
380
+ */
381
+ interface FieldMetadata {
382
+ requiresScope?: string | string[];
383
+ deprecated?: boolean | string;
384
+ description?: string;
385
+ }
386
+ /**
387
+ * Field definition in a GraphQL type.
388
+ */
389
+ interface Field extends FieldMetadata {
390
+ name: string;
391
+ type: string;
392
+ nullable: boolean;
393
+ default?: unknown;
394
+ }
395
+ /**
396
+ * GraphQL type definition.
397
+ */
398
+ interface TypeDefinition {
399
+ name: string;
400
+ fields: Field[];
401
+ description?: string;
402
+ relay?: boolean;
403
+ sql_source?: string;
404
+ jsonb_column?: string;
405
+ is_error?: boolean;
406
+ requires_role?: string;
407
+ implements?: string[];
408
+ }
409
+ /**
410
+ * Argument definition for a query or mutation.
411
+ */
412
+ interface ArgumentDefinition {
413
+ name: string;
414
+ type: string;
415
+ nullable: boolean;
416
+ default?: unknown;
417
+ }
418
+ /**
419
+ * GraphQL query definition.
420
+ */
421
+ interface QueryDefinition {
422
+ name: string;
423
+ return_type: string;
424
+ returns_list: boolean;
425
+ nullable: boolean;
426
+ arguments: ArgumentDefinition[];
427
+ description?: string;
428
+ [key: string]: unknown;
429
+ }
430
+ /**
431
+ * GraphQL mutation definition.
432
+ */
433
+ interface MutationDefinition {
434
+ name: string;
435
+ return_type: string;
436
+ returns_list: boolean;
437
+ nullable: boolean;
438
+ arguments: ArgumentDefinition[];
439
+ description?: string;
440
+ operation?: string;
441
+ [key: string]: unknown;
442
+ }
443
+ /**
444
+ * Measure definition in a fact table.
445
+ */
446
+ interface Measure {
447
+ name: string;
448
+ sql_type: string;
449
+ nullable: boolean;
450
+ }
451
+ /**
452
+ * Dimension path in a fact table.
453
+ */
454
+ interface DimensionPath {
455
+ name: string;
456
+ json_path: string;
457
+ data_type: string;
458
+ }
459
+ /**
460
+ * Dimension definition in a fact table.
461
+ */
462
+ interface Dimension {
463
+ name: string;
464
+ paths: DimensionPath[];
465
+ }
466
+ /**
467
+ * Denormalized filter in a fact table.
468
+ */
469
+ interface DenormalizedFilter {
470
+ name: string;
471
+ sql_type: string;
472
+ indexed: boolean;
473
+ }
474
+ /**
475
+ * Fact table definition.
476
+ */
477
+ interface FactTableDefinition {
478
+ table_name: string;
479
+ measures: Measure[];
480
+ dimensions: Dimension;
481
+ denormalized_filters: DenormalizedFilter[];
482
+ }
483
+ /**
484
+ * Aggregate query definition.
485
+ */
486
+ interface AggregateQueryDefinition {
487
+ name: string;
488
+ fact_table: string;
489
+ auto_group_by: boolean;
490
+ auto_aggregates: boolean;
491
+ description?: string;
492
+ }
493
+ /**
494
+ * GraphQL subscription definition.
495
+ *
496
+ * Subscriptions in FraiseQL are compiled projections of database events.
497
+ * They are sourced from LISTEN/NOTIFY or CDC, not resolver-based.
498
+ */
499
+ interface SubscriptionDefinition {
500
+ name: string;
501
+ entity_type: string;
502
+ nullable: boolean;
503
+ arguments: ArgumentDefinition[];
504
+ description?: string;
505
+ topic?: string;
506
+ operation?: string;
507
+ [key: string]: unknown;
508
+ }
509
+ /**
510
+ * Observer action definition.
511
+ */
512
+ interface ObserverAction {
513
+ type: "webhook" | "slack" | "email";
514
+ [key: string]: unknown;
515
+ }
516
+ /**
517
+ * Observer retry configuration.
518
+ */
519
+ interface ObserverRetryConfig {
520
+ max_attempts: number;
521
+ backoff_strategy: string;
522
+ initial_delay_ms: number;
523
+ max_delay_ms: number;
524
+ }
525
+ /**
526
+ * Observer definition.
527
+ */
528
+ interface ObserverDefinition {
529
+ name: string;
530
+ entity: string;
531
+ event: string;
532
+ actions: ObserverAction[];
533
+ condition?: string;
534
+ retry: ObserverRetryConfig;
535
+ }
536
+ /**
537
+ * Enum value definition.
538
+ */
539
+ interface EnumValue {
540
+ name: string;
541
+ deprecated?: {
542
+ reason: string;
543
+ };
544
+ }
545
+ /**
546
+ * GraphQL enum definition.
547
+ */
548
+ interface EnumDefinition {
549
+ name: string;
550
+ values: EnumValue[];
551
+ description?: string;
552
+ }
553
+ /**
554
+ * GraphQL interface definition.
555
+ */
556
+ interface InterfaceDefinition {
557
+ name: string;
558
+ fields: Field[];
559
+ description?: string;
560
+ }
561
+ /**
562
+ * GraphQL input type definition.
563
+ */
564
+ interface InputTypeDefinition {
565
+ name: string;
566
+ fields: Array<Field & {
567
+ default?: unknown;
568
+ }>;
569
+ description?: string;
570
+ }
571
+ /**
572
+ * GraphQL union definition.
573
+ */
574
+ interface UnionDefinition {
575
+ name: string;
576
+ member_types: string[];
577
+ description?: string;
578
+ }
579
+ /**
580
+ * Complete schema definition.
581
+ */
582
+ interface Schema {
583
+ types: TypeDefinition[];
584
+ queries: QueryDefinition[];
585
+ mutations: MutationDefinition[];
586
+ subscriptions: SubscriptionDefinition[];
587
+ enums?: EnumDefinition[];
588
+ interfaces?: InterfaceDefinition[];
589
+ input_types?: InputTypeDefinition[];
590
+ unions?: UnionDefinition[];
591
+ fact_tables?: FactTableDefinition[];
592
+ aggregate_queries?: AggregateQueryDefinition[];
593
+ observers?: ObserverDefinition[];
594
+ /** Apollo Federation v2 metadata, included when generateSchemaJson() is used. */
595
+ federation?: {
596
+ enabled: boolean;
597
+ version: string;
598
+ [key: string]: unknown;
599
+ };
600
+ /** Custom scalar definitions, included when scalars are registered. */
601
+ customScalars?: Record<string, {
602
+ name: string;
603
+ description: string;
604
+ validate: boolean;
605
+ }>;
606
+ }
607
+ /**
608
+ * Global schema registry (singleton).
609
+ *
610
+ * Maintains maps of all registered types, queries, mutations, and analytics definitions.
611
+ * These are collected during decorator evaluation and exported to schema.json.
612
+ */
613
+ declare class SchemaRegistry {
614
+ private static types;
615
+ private static queries;
616
+ private static mutations;
617
+ private static subscriptions;
618
+ private static enums;
619
+ private static interfaces;
620
+ private static inputTypes;
621
+ private static unions;
622
+ private static factTables;
623
+ private static aggregateQueries;
624
+ private static observers;
625
+ private static customScalars;
626
+ /**
627
+ * Register a GraphQL type.
628
+ *
629
+ * @param name - Type name (e.g., "User")
630
+ * @param fields - List of field definitions
631
+ * @param description - Optional type description
632
+ * @param options - Additional type options
633
+ */
634
+ static registerType(name: string, fields: Field[], description?: string, options?: {
635
+ relay?: boolean;
636
+ sqlSource?: string;
637
+ jsonbColumn?: string;
638
+ isError?: boolean;
639
+ requiresRole?: string;
640
+ implements?: string[];
641
+ }): void;
642
+ /**
643
+ * Register a GraphQL query.
644
+ *
645
+ * @param name - Query name
646
+ * @param returnType - Return type name
647
+ * @param returnsList - Whether query returns a list
648
+ * @param nullable - Whether result can be null
649
+ * @param args - List of argument definitions
650
+ * @param description - Optional query description
651
+ * @param config - Additional configuration (sql_source, etc.)
652
+ */
653
+ static registerQuery(name: string, returnType: string, returnsList: boolean, nullable: boolean, args: ArgumentDefinition[], description?: string, config?: Record<string, unknown>): void;
654
+ /**
655
+ * Register a GraphQL mutation.
656
+ *
657
+ * @param name - Mutation name
658
+ * @param returnType - Return type name
659
+ * @param returnsList - Whether mutation returns a list
660
+ * @param nullable - Whether result can be null
661
+ * @param args - List of argument definitions
662
+ * @param description - Optional mutation description
663
+ * @param config - Additional configuration (sql_source, operation, etc.)
664
+ */
665
+ static registerMutation(name: string, returnType: string, returnsList: boolean, nullable: boolean, args: ArgumentDefinition[], description?: string, config?: Record<string, unknown>): void;
666
+ /**
667
+ * Register a GraphQL subscription.
668
+ *
669
+ * Subscriptions in FraiseQL are compiled projections of database events.
670
+ * They are sourced from LISTEN/NOTIFY or CDC, not resolver-based.
671
+ *
672
+ * @param name - Subscription name
673
+ * @param entityType - Entity type name being subscribed to
674
+ * @param nullable - Whether result can be null
675
+ * @param args - List of argument definitions (filters)
676
+ * @param description - Optional subscription description
677
+ * @param config - Additional configuration (topic, operation, etc.)
678
+ */
679
+ static registerSubscription(name: string, entityType: string, nullable: boolean, args: ArgumentDefinition[], description?: string, config?: Record<string, unknown>): void;
680
+ /**
681
+ * Register a fact table definition.
682
+ *
683
+ * @param tableName - Fact table name
684
+ * @param measures - List of measure definitions
685
+ * @param dimensions - Dimension metadata
686
+ * @param denormalizedFilters - List of denormalized filter definitions
687
+ */
688
+ static registerFactTable(tableName: string, measures: Measure[], dimensions: Dimension, denormalizedFilters: DenormalizedFilter[]): void;
689
+ /**
690
+ * Register an aggregate query definition.
691
+ *
692
+ * @param name - Query name
693
+ * @param factTable - Fact table name
694
+ * @param autoGroupBy - Auto-generate groupBy fields
695
+ * @param autoAggregates - Auto-generate aggregate fields
696
+ * @param description - Optional query description
697
+ */
698
+ static registerAggregateQuery(name: string, factTable: string, autoGroupBy: boolean, autoAggregates: boolean, description?: string): void;
699
+ /**
700
+ * Register an observer.
701
+ *
702
+ * @param name - Observer function name
703
+ * @param entity - Entity type to observe
704
+ * @param event - Event type (INSERT, UPDATE, or DELETE)
705
+ * @param actions - List of action configurations
706
+ * @param condition - Optional condition expression
707
+ * @param retry - Retry configuration
708
+ */
709
+ static registerObserver(name: string, entity: string, event: string, actions: ObserverAction[], condition?: string, retry?: ObserverRetryConfig): void;
710
+ /**
711
+ * Register a GraphQL enum type.
712
+ *
713
+ * @param name - Enum name (e.g., "OrderStatus")
714
+ * @param values - List of enum value definitions
715
+ * @param description - Optional enum description
716
+ */
717
+ static registerEnum(name: string, values: EnumValue[], description?: string): void;
718
+ /**
719
+ * Register a GraphQL interface type.
720
+ *
721
+ * @param name - Interface name (e.g., "Node")
722
+ * @param fields - List of field definitions
723
+ * @param description - Optional interface description
724
+ */
725
+ static registerInterface(name: string, fields: Field[], description?: string): void;
726
+ /**
727
+ * Register a GraphQL input type.
728
+ *
729
+ * @param name - Input type name (e.g., "CreateUserInput")
730
+ * @param fields - List of field definitions with optional defaults
731
+ * @param description - Optional input type description
732
+ */
733
+ static registerInputType(name: string, fields: Array<Field & {
734
+ default?: unknown;
735
+ }>, description?: string): void;
736
+ /**
737
+ * Register a GraphQL union type.
738
+ *
739
+ * @param name - Union name (e.g., "SearchResult")
740
+ * @param memberTypes - List of member type names
741
+ * @param description - Optional union description
742
+ */
743
+ static registerUnion(name: string, memberTypes: string[], description?: string): void;
744
+ /**
745
+ * Register a custom scalar.
746
+ *
747
+ * @param name - Scalar name (e.g., "Email")
748
+ * @param scalarClass - The CustomScalar subclass
749
+ * @param description - Optional scalar description
750
+ *
751
+ * @throws If scalar name is not unique
752
+ */
753
+ static registerScalar(name: string, scalarClass: typeof CustomScalar, description?: string): void;
754
+ /**
755
+ * Get all registered custom scalars.
756
+ *
757
+ * @returns Map of scalar names to CustomScalar classes
758
+ */
759
+ static getCustomScalars(): Map<string, typeof CustomScalar>;
760
+ /**
761
+ * Get the complete schema as an object.
762
+ *
763
+ * @returns Schema object with types, queries, mutations, subscriptions, and analytics sections
764
+ */
765
+ static getSchema(): Schema;
766
+ /**
767
+ * Clear the registry (useful for testing).
768
+ */
769
+ static clear(): void;
770
+ }
771
+
772
+ /**
773
+ * Decorators for FraiseQL schema authoring (compile-time only).
774
+ *
775
+ * These decorators register type and query definitions with the schema registry
776
+ * for JSON export. NO runtime behavior - only metadata collection.
777
+ */
778
+
779
+ /**
780
+ * Create field-level metadata for access control and deprecation.
781
+ *
782
+ * This function creates metadata for use with field definitions to add:
783
+ * - `requiresScope`: JWT scope required to access this field
784
+ * - `deprecated`: Deprecation marker with optional reason
785
+ * - `description`: Field description for GraphQL schema
786
+ *
787
+ * @param options - Field metadata options
788
+ * @returns Field metadata object
789
+ *
790
+ * @example
791
+ * ```typescript
792
+ * fraiseql.registerTypeFields("User", [
793
+ * { name: "id", type: "ID", nullable: false },
794
+ * {
795
+ * name: "salary",
796
+ * type: "Decimal",
797
+ * nullable: false,
798
+ * requiresScope: "read:User.salary" // Requires JWT scope
799
+ * },
800
+ * {
801
+ * name: "oldEmail",
802
+ * type: "String",
803
+ * nullable: true,
804
+ * deprecated: "Use email instead" // Deprecation marker
805
+ * }
806
+ * ]);
807
+ * ```
808
+ */
809
+ declare function field(options: FieldMetadata): FieldMetadata;
810
+ /**
811
+ * Configuration for a Type decorator.
812
+ */
813
+ interface TypeConfig {
814
+ description?: string;
815
+ relay?: boolean;
816
+ sqlSource?: string;
817
+ crud?: boolean | string[];
818
+ cascade?: boolean;
819
+ }
820
+ /**
821
+ * Decorator to mark a class as a GraphQL type.
822
+ *
823
+ * This decorator registers the class with the schema registry for JSON export.
824
+ * NO runtime behavior - only used for schema compilation.
825
+ *
826
+ * @param config - Optional configuration
827
+ * @returns Decorator function
828
+ *
829
+ * @example
830
+ * ```ts
831
+ * @Type()
832
+ * class User {
833
+ * id: number;
834
+ * name: string;
835
+ * email: string | null;
836
+ * }
837
+ * ```
838
+ *
839
+ * This generates JSON:
840
+ * ```json
841
+ * {
842
+ * "name": "User",
843
+ * "fields": [
844
+ * {"name": "id", "type": "Int", "nullable": false},
845
+ * {"name": "name", "type": "String", "nullable": false},
846
+ * {"name": "email", "type": "String", "nullable": true}
847
+ * ]
848
+ * }
849
+ * ```
850
+ */
851
+ declare function Type(_config?: TypeConfig): <T extends {
852
+ new (...args: any[]): object;
853
+ }>(constructor: T) => T;
854
+ /**
855
+ * Configuration for Query and Mutation decorators.
856
+ */
857
+ interface OperationConfig {
858
+ sqlSource?: string;
859
+ autoParams?: Record<string, boolean>;
860
+ operation?: string;
861
+ jsonbColumn?: string;
862
+ relay?: boolean;
863
+ [key: string]: unknown;
864
+ }
865
+ /**
866
+ * Decorator to mark a function as a GraphQL query.
867
+ *
868
+ * This decorator registers the function with the schema registry for JSON export.
869
+ * NO runtime behavior - only used for schema compilation.
870
+ *
871
+ * Configuration is provided via parameters:
872
+ * - sqlSource: SQL view name or table name
873
+ * - autoParams: Auto-parameter configuration
874
+ * - Other configuration as needed
875
+ *
876
+ * @param config - Query configuration
877
+ * @returns Decorator function
878
+ *
879
+ * @example
880
+ * ```ts
881
+ * @Query({ sqlSource: "v_user" })
882
+ * function users(limit: number = 10, offset: number = 0): User[] {
883
+ * pass;
884
+ * }
885
+ * ```
886
+ *
887
+ * This generates JSON:
888
+ * ```json
889
+ * {
890
+ * "name": "users",
891
+ * "return_type": "User",
892
+ * "returns_list": true,
893
+ * "nullable": false,
894
+ * "arguments": [
895
+ * {"name": "limit", "type": "Int", "nullable": false, "default": 10},
896
+ * {"name": "offset", "type": "Int", "nullable": false, "default": 0}
897
+ * ],
898
+ * "sql_source": "v_user"
899
+ * }
900
+ * ```
901
+ */
902
+ declare function Query(config?: OperationConfig): (_target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
903
+ /**
904
+ * Configuration for Mutation decorator.
905
+ */
906
+ interface MutationConfig extends OperationConfig {
907
+ operation?: "CREATE" | "UPDATE" | "DELETE" | "CUSTOM";
908
+ }
909
+ /**
910
+ * Decorator to mark a function as a GraphQL mutation.
911
+ *
912
+ * This decorator registers the function with the schema registry for JSON export.
913
+ * NO runtime behavior - only used for schema compilation.
914
+ *
915
+ * @param config - Mutation configuration
916
+ * @returns Decorator function
917
+ *
918
+ * @example
919
+ * ```ts
920
+ * @Mutation({ sqlSource: "fn_create_user", operation: "CREATE" })
921
+ * function createUser(name: string, email: string): User {
922
+ * pass;
923
+ * }
924
+ * ```
925
+ *
926
+ * This generates JSON:
927
+ * ```json
928
+ * {
929
+ * "name": "createUser",
930
+ * "return_type": "User",
931
+ * "returns_list": false,
932
+ * "nullable": false,
933
+ * "arguments": [
934
+ * {"name": "name", "type": "String", "nullable": false},
935
+ * {"name": "email", "type": "String", "nullable": false}
936
+ * ],
937
+ * "sql_source": "fn_create_user",
938
+ * "operation": "CREATE"
939
+ * }
940
+ * ```
941
+ */
942
+ declare function Mutation(config?: MutationConfig): (_target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
943
+ /**
944
+ * Configuration for Enum decorator.
945
+ */
946
+ interface EnumConfig {
947
+ description?: string;
948
+ }
949
+ /**
950
+ * Decorator to mark an object as a GraphQL enum.
951
+ *
952
+ * This decorator registers the enum with the schema registry for JSON export.
953
+ * NO runtime behavior - only used for schema compilation.
954
+ *
955
+ * @param values - Object with enum values as keys (values are not used, only keys matter)
956
+ * @param config - Optional configuration
957
+ * @returns Decorator function
958
+ *
959
+ * @example
960
+ * ```ts
961
+ * const OrderStatus = enum('OrderStatus', {
962
+ * PENDING: 'pending',
963
+ * SHIPPED: 'shipped',
964
+ * DELIVERED: 'delivered'
965
+ * }, {
966
+ * description: 'The status of an order'
967
+ * })
968
+ * ```
969
+ *
970
+ * This generates JSON:
971
+ * ```json
972
+ * {
973
+ * "name": "OrderStatus",
974
+ * "description": "The status of an order",
975
+ * "values": [
976
+ * {"name": "PENDING"},
977
+ * {"name": "SHIPPED"},
978
+ * {"name": "DELIVERED"}
979
+ * ]
980
+ * }
981
+ * ```
982
+ */
983
+ declare function enum_(name: string, values: Record<string, unknown>, config?: EnumConfig): Record<string, unknown>;
984
+ /**
985
+ * Configuration for Interface decorator.
986
+ */
987
+ interface InterfaceConfig {
988
+ description?: string;
989
+ }
990
+ /**
991
+ * Decorator to mark a class as a GraphQL interface.
992
+ *
993
+ * This decorator registers the interface with the schema registry for JSON export.
994
+ * NO runtime behavior - only used for schema compilation.
995
+ *
996
+ * Interfaces define a common set of fields that multiple object types can implement.
997
+ * Per GraphQL spec §3.7, interfaces enable polymorphic queries.
998
+ *
999
+ * @param name - Interface name
1000
+ * @param fields - Field definitions
1001
+ * @param config - Optional configuration
1002
+ * @returns Interface marker object
1003
+ *
1004
+ * @example
1005
+ * ```ts
1006
+ * const Node = interface('Node', {
1007
+ * id: { type: 'ID', nullable: false },
1008
+ * createdAt: { type: 'DateTime', nullable: false }
1009
+ * }, {
1010
+ * description: 'An object with a globally unique ID'
1011
+ * })
1012
+ * ```
1013
+ */
1014
+ declare function interface_(name: string, fields: Field[], config?: InterfaceConfig): Record<string, unknown>;
1015
+ /**
1016
+ * Configuration for Union decorator.
1017
+ */
1018
+ interface UnionConfig {
1019
+ description?: string;
1020
+ }
1021
+ /**
1022
+ * Decorator to mark a class as a GraphQL union type.
1023
+ *
1024
+ * Per GraphQL spec §3.10, unions represent a type that could be one of
1025
+ * several object types. Unlike interfaces, unions don't define common fields.
1026
+ *
1027
+ * This decorator registers the union with the schema registry for JSON export.
1028
+ * NO runtime behavior - only used for schema compilation.
1029
+ *
1030
+ * @param name - Union name
1031
+ * @param memberTypes - List of member type names
1032
+ * @param config - Optional configuration
1033
+ * @returns Union marker object
1034
+ *
1035
+ * @example
1036
+ * ```ts
1037
+ * const SearchResult = union('SearchResult', ['User', 'Post', 'Comment'], {
1038
+ * description: 'Result of a search query'
1039
+ * })
1040
+ * ```
1041
+ */
1042
+ declare function union(name: string, memberTypes: string[], config?: UnionConfig): Record<string, unknown>;
1043
+ /**
1044
+ * Configuration for Input decorator.
1045
+ */
1046
+ interface InputConfig {
1047
+ description?: string;
1048
+ }
1049
+ /**
1050
+ * Decorator to mark a class as a GraphQL input type.
1051
+ *
1052
+ * This decorator registers the input type with the schema registry for JSON export.
1053
+ * NO runtime behavior - only used for schema compilation.
1054
+ *
1055
+ * @param name - Input type name
1056
+ * @param fields - Field definitions with optional defaults
1057
+ * @param config - Optional configuration
1058
+ * @returns Input marker object
1059
+ *
1060
+ * @example
1061
+ * ```ts
1062
+ * const CreateUserInput = input('CreateUserInput', [
1063
+ * { name: 'name', type: 'String', nullable: false },
1064
+ * { name: 'email', type: 'String', nullable: false },
1065
+ * { name: 'role', type: 'String', nullable: false, default: 'user' }
1066
+ * ], {
1067
+ * description: 'Input for creating a new user'
1068
+ * })
1069
+ * ```
1070
+ */
1071
+ declare function input(name: string, fields: Array<Field & {
1072
+ default?: unknown;
1073
+ }>, config?: InputConfig): Record<string, unknown>;
1074
+ /**
1075
+ * Helper function to manually register type fields with metadata.
1076
+ *
1077
+ * Since TypeScript doesn't preserve type information at runtime by default,
1078
+ * this helper allows explicit field registration for types.
1079
+ *
1080
+ * @param typeName - Name of the type
1081
+ * @param fields - Field definitions
1082
+ * @param description - Optional type description
1083
+ *
1084
+ * @example
1085
+ * ```ts
1086
+ * @Type()
1087
+ * class User {
1088
+ * id: number;
1089
+ * name: string;
1090
+ * email: string | null;
1091
+ * }
1092
+ *
1093
+ * registerTypeFields("User", [
1094
+ * { name: "id", type: "Int", nullable: false },
1095
+ * { name: "name", type: "String", nullable: false },
1096
+ * { name: "email", type: "String", nullable: true }
1097
+ * ]);
1098
+ * ```
1099
+ */
1100
+ declare function registerTypeFields(typeName: string, fields: Field[], description?: string, options?: {
1101
+ relay?: boolean;
1102
+ sqlSource?: string;
1103
+ jsonbColumn?: string;
1104
+ isError?: boolean;
1105
+ requiresRole?: string;
1106
+ implements?: string[];
1107
+ crud?: boolean | string[];
1108
+ cascade?: boolean;
1109
+ }): void;
1110
+ /**
1111
+ * Helper function to manually register query with full metadata.
1112
+ *
1113
+ * @param name - Query name
1114
+ * @param returnType - Return type name
1115
+ * @param returnsList - Whether query returns a list
1116
+ * @param nullable - Whether result can be null
1117
+ * @param args - Argument definitions
1118
+ * @param description - Optional query description
1119
+ * @param config - Additional configuration
1120
+ *
1121
+ * @example
1122
+ * ```ts
1123
+ * registerQuery(
1124
+ * "users",
1125
+ * "User",
1126
+ * true,
1127
+ * false,
1128
+ * [
1129
+ * { name: "limit", type: "Int", nullable: false, default: 10 },
1130
+ * { name: "offset", type: "Int", nullable: false, default: 0 }
1131
+ * ],
1132
+ * "Get list of users",
1133
+ * { sql_source: "v_user" }
1134
+ * );
1135
+ * ```
1136
+ */
1137
+ declare function registerQuery(name: string, returnType: string, returnsList: boolean, nullable: boolean, args: ArgumentDefinition[], description?: string, config?: Record<string, unknown>): void;
1138
+ /**
1139
+ * Helper function to manually register mutation with full metadata.
1140
+ *
1141
+ * @param name - Mutation name
1142
+ * @param returnType - Return type name
1143
+ * @param returnsList - Whether mutation returns a list
1144
+ * @param nullable - Whether result can be null
1145
+ * @param args - Argument definitions
1146
+ * @param description - Optional mutation description
1147
+ * @param config - Additional configuration
1148
+ */
1149
+ declare function registerMutation(name: string, returnType: string, returnsList: boolean, nullable: boolean, args: ArgumentDefinition[], description?: string, config?: Record<string, unknown>): void;
1150
+ /**
1151
+ * Configuration for Subscription decorator.
1152
+ */
1153
+ interface SubscriptionConfig {
1154
+ entityType?: string;
1155
+ topic?: string;
1156
+ operation?: "CREATE" | "UPDATE" | "DELETE";
1157
+ [key: string]: unknown;
1158
+ }
1159
+ /**
1160
+ * Decorator to mark a function as a GraphQL subscription.
1161
+ *
1162
+ * This decorator registers the function with the schema registry for JSON export.
1163
+ * NO runtime behavior - only used for schema compilation.
1164
+ *
1165
+ * Subscriptions in FraiseQL are compiled projections of database events.
1166
+ * They are sourced from LISTEN/NOTIFY or CDC, not resolver-based.
1167
+ *
1168
+ * @param config - Subscription configuration
1169
+ * @returns Decorator function
1170
+ *
1171
+ * @example
1172
+ * ```ts
1173
+ * @Subscription({ topic: "order_events" })
1174
+ * function orderCreated(userId?: string): Order {
1175
+ * pass;
1176
+ * }
1177
+ * ```
1178
+ *
1179
+ * This generates JSON:
1180
+ * ```json
1181
+ * {
1182
+ * "name": "orderCreated",
1183
+ * "entity_type": "Order",
1184
+ * "nullable": false,
1185
+ * "arguments": [
1186
+ * {"name": "userId", "type": "String", "nullable": true}
1187
+ * ],
1188
+ * "topic": "order_events"
1189
+ * }
1190
+ * ```
1191
+ */
1192
+ declare function Subscription(config?: SubscriptionConfig): (_target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
1193
+ /**
1194
+ * Helper function to manually register subscription with full metadata.
1195
+ *
1196
+ * @param name - Subscription name
1197
+ * @param entityType - Entity type being subscribed to
1198
+ * @param nullable - Whether result can be null
1199
+ * @param args - Argument definitions (filters)
1200
+ * @param description - Optional subscription description
1201
+ * @param config - Additional configuration (topic, operation)
1202
+ *
1203
+ * @example
1204
+ * ```ts
1205
+ * registerSubscription(
1206
+ * "orderCreated",
1207
+ * "Order",
1208
+ * false,
1209
+ * [
1210
+ * { name: "userId", type: "String", nullable: true }
1211
+ * ],
1212
+ * "Subscribe to new orders",
1213
+ * { topic: "order_events", operation: "CREATE" }
1214
+ * );
1215
+ * ```
1216
+ */
1217
+ declare function registerSubscription(name: string, entityType: string, nullable: boolean, args: ArgumentDefinition[], description?: string, config?: Record<string, unknown>): void;
1218
+ /**
1219
+ * Decorator to register a custom scalar with the schema.
1220
+ *
1221
+ * This decorator registers the scalar globally so it can be:
1222
+ * 1. Used in type annotations
1223
+ * 2. Exported to schema.json
1224
+ * 3. Validated at runtime
1225
+ *
1226
+ * @param target - CustomScalar subclass
1227
+ * @returns The original class (unmodified)
1228
+ * @throws If scalar name is not unique
1229
+ * @throws If class doesn't extend CustomScalar
1230
+ *
1231
+ * @example
1232
+ * ```typescript
1233
+ * @Scalar()
1234
+ * class Email extends CustomScalar {
1235
+ * name = "Email"
1236
+ *
1237
+ * serialize(value: unknown): string {
1238
+ * return String(value)
1239
+ * }
1240
+ *
1241
+ * parseValue(value: unknown): string {
1242
+ * const str = String(value)
1243
+ * if (!str.includes("@")) {
1244
+ * throw new Error("Invalid email")
1245
+ * }
1246
+ * return str
1247
+ * }
1248
+ *
1249
+ * parseLiteral(ast: unknown): string {
1250
+ * if (ast && typeof ast === "object" && "value" in ast) {
1251
+ * return this.parseValue((ast as any).value)
1252
+ * }
1253
+ * throw new Error("Invalid email literal")
1254
+ * }
1255
+ * }
1256
+ *
1257
+ * // Use in type:
1258
+ * @Type()
1259
+ * class User {
1260
+ * id: string
1261
+ * email: Email // Uses registered Email scalar
1262
+ * name: string
1263
+ * }
1264
+ *
1265
+ * // Export schema
1266
+ * const schema = exportSchema("schema.json")
1267
+ * // schema contains: "customScalars": {"Email": {...}}
1268
+ * ```
1269
+ *
1270
+ * @remarks
1271
+ * - Decorator returns class unmodified (no runtime FFI)
1272
+ * - Registration is global (per-process)
1273
+ * - Name must be unique within schema
1274
+ * - Scalar must be defined before @Type that uses it
1275
+ */
1276
+ declare function Scalar<T extends typeof CustomScalar>(target: T): T;
1277
+
1278
+ /**
1279
+ * CRUD operation generation for FraiseQL types.
1280
+ *
1281
+ * When `crud` is enabled on a type, this module auto-generates standard
1282
+ * GraphQL queries (get-by-ID, list) and mutations (create, update, delete)
1283
+ * following FraiseQL naming conventions.
1284
+ */
1285
+
1286
+ /**
1287
+ * Generate CRUD queries and mutations for a type.
1288
+ *
1289
+ * @param typeName - The GraphQL type name (PascalCase)
1290
+ * @param fields - The type's field definitions
1291
+ * @param crud - `true` for all operations, or an array of specific operations
1292
+ * @param sqlSource - Optional SQL source override (defaults to `v_{snake_name}`)
1293
+ * @param cascade - Whether generated mutations include `cascade: true`
1294
+ *
1295
+ * @throws If `crud` contains unknown operation names
1296
+ * @throws If the type has no fields
1297
+ */
1298
+ declare function generateCrudOperations(typeName: string, fields: Field[], crud: boolean | string[], sqlSource?: string, cascade?: boolean): void;
1299
+
1300
+ /**
1301
+ * Schema export functionality for FraiseQL.
1302
+ *
1303
+ * This module provides functions to export the schema registry to JSON files
1304
+ * that can be consumed by the fraiseql-cli compiler.
1305
+ */
1306
+
1307
+ /**
1308
+ * Configuration helper for queries and mutations.
1309
+ *
1310
+ * This function is called inside decorated functions to specify SQL mapping
1311
+ * and other configuration. The config is stored temporarily and applied by
1312
+ * the decorator.
1313
+ *
1314
+ * @param config - Configuration options:
1315
+ * - sqlSource: SQL view name (queries) or function name (mutations)
1316
+ * - operation: Mutation operation type (CREATE, UPDATE, DELETE, CUSTOM)
1317
+ * - autoParams: Auto-parameter configuration (limit, offset, where, order_by)
1318
+ * - jsonbColumn: JSONB column name for flexible schemas
1319
+ *
1320
+ * @example
1321
+ * ```ts
1322
+ * @Query()
1323
+ * function users(limit: number = 10) {
1324
+ * return config({
1325
+ * sqlSource: "v_user",
1326
+ * autoParams: { limit: true, offset: true, where: true }
1327
+ * });
1328
+ * }
1329
+ *
1330
+ * @Mutation()
1331
+ * function createUser(name: string, email: string) {
1332
+ * return config({
1333
+ * sqlSource: "fn_create_user",
1334
+ * operation: "CREATE"
1335
+ * });
1336
+ * }
1337
+ * ```
1338
+ */
1339
+ declare function config(configObj: Record<string, unknown>): void;
1340
+ /**
1341
+ * Export the schema registry to a JSON file.
1342
+ *
1343
+ * This function should be called after all decorators have been processed
1344
+ * (typically at the end of the schema definition file).
1345
+ *
1346
+ * @param outputPath - Path to output schema.json file
1347
+ * @param options - Export options
1348
+ *
1349
+ * @example
1350
+ * ```ts
1351
+ * // At end of schema.ts
1352
+ * if (require.main === module) {
1353
+ * exportSchema("schema.json");
1354
+ * }
1355
+ * ```
1356
+ *
1357
+ * Notes:
1358
+ * - Call this after all decorators have been applied
1359
+ * - The output schema.json is consumed by fraiseql-cli
1360
+ * - Pretty formatting is recommended for version control
1361
+ */
1362
+ declare function exportSchema(outputPath: string, options?: {
1363
+ pretty?: boolean;
1364
+ }): void;
1365
+ /**
1366
+ * Get the current schema as a dictionary (without exporting to file).
1367
+ *
1368
+ * @returns Schema object with "types", "queries", and "mutations"
1369
+ *
1370
+ * @example
1371
+ * ```ts
1372
+ * const schema = getSchemaDict();
1373
+ * console.log(schema.types);
1374
+ * // [{ name: "User", fields: [...] }, ...]
1375
+ * ```
1376
+ */
1377
+ declare function getSchemaDict(): Schema;
1378
+ /**
1379
+ * Export schema to a JSON string instead of a file.
1380
+ *
1381
+ * @param options - Export options
1382
+ * @returns JSON string representation of the schema
1383
+ *
1384
+ * @example
1385
+ * ```ts
1386
+ * const jsonString = exportSchemaToString({ pretty: true });
1387
+ * console.log(jsonString);
1388
+ * ```
1389
+ */
1390
+ declare function exportSchemaToString(options?: {
1391
+ pretty?: boolean;
1392
+ }): string;
1393
+ /**
1394
+ * Export ONLY types to a minimal types.json file (TOML-based workflow).
1395
+ *
1396
+ * This is the new minimal export function for the TOML-based configuration approach.
1397
+ * It exports only the type definitions (types, enums, input_types, interfaces) without
1398
+ * queries, mutations, federation, security, observers, or analytics metadata.
1399
+ *
1400
+ * All configuration moves to fraiseql.toml, which is merged with this types.json
1401
+ * by the fraiseql-cli compile command.
1402
+ *
1403
+ * @param outputPath - Path to output types.json file
1404
+ * @param options - Export options
1405
+ *
1406
+ * @example
1407
+ * ```ts
1408
+ * // At end of schema.ts
1409
+ * if (require.main === module) {
1410
+ * exportTypes("user_types.json");
1411
+ * }
1412
+ * ```
1413
+ *
1414
+ * Notes:
1415
+ * - Call this after all decorators have been applied
1416
+ * - The output types.json contains only type definitions
1417
+ * - Queries, mutations, and all configuration moves to fraiseql.toml
1418
+ * - Use with: fraiseql compile fraiseql.toml --types user_types.json
1419
+ */
1420
+ declare function exportTypes(outputPath: string, options?: {
1421
+ pretty?: boolean;
1422
+ }): void;
1423
+
1424
+ /**
1425
+ * Validation engine for custom GraphQL scalars.
1426
+ */
1427
+
1428
+ /**
1429
+ * Raised when custom scalar validation fails.
1430
+ */
1431
+ declare class ScalarValidationError extends Error {
1432
+ scalarName: string;
1433
+ context: "serialize" | "parseValue" | "parseLiteral";
1434
+ /**
1435
+ * Creates a new ScalarValidationError.
1436
+ *
1437
+ * @param scalarName - Name of the scalar that failed validation
1438
+ * @param context - The validation context ("serialize", "parseValue", or "parseLiteral")
1439
+ * @param message - The underlying error message
1440
+ */
1441
+ constructor(scalarName: string, context: "serialize" | "parseValue" | "parseLiteral", message: string);
1442
+ }
1443
+ /**
1444
+ * Execute validation for a custom scalar.
1445
+ *
1446
+ * @param scalarClass - The CustomScalar subclass to validate with
1447
+ * @param value - The value to validate
1448
+ * @param context - One of "serialize", "parseValue", or "parseLiteral"
1449
+ * @returns The validated/converted value
1450
+ * @throws ScalarValidationError if validation fails
1451
+ * @throws Error if context is unknown
1452
+ *
1453
+ * @example
1454
+ * ```typescript
1455
+ * import { validateCustomScalar } from "fraiseql/validators"
1456
+ * import { Email } from "./scalars"
1457
+ *
1458
+ * // Parse a variable value from GraphQL
1459
+ * const emailValue = validateCustomScalar(Email, "user@example.com", "parseValue")
1460
+ * // Returns "user@example.com"
1461
+ *
1462
+ * // Validation fails
1463
+ * try {
1464
+ * validateCustomScalar(Email, "invalid-email", "parseValue")
1465
+ * } catch (e) {
1466
+ * // ScalarValidationError: Scalar "Email" validation failed in parseValue: Invalid email
1467
+ * }
1468
+ * ```
1469
+ */
1470
+ declare function validateCustomScalar(scalarClass: typeof CustomScalar, value: unknown, context?: "serialize" | "parseValue" | "parseLiteral"): unknown;
1471
+ /**
1472
+ * Get all registered custom scalars.
1473
+ *
1474
+ * @returns Map of scalar names to CustomScalar classes
1475
+ *
1476
+ * @example
1477
+ * ```typescript
1478
+ * import { getAllCustomScalars } from "fraiseql/validators"
1479
+ *
1480
+ * const scalars = getAllCustomScalars()
1481
+ * // Map { "Email" => class Email, "Phone" => class Phone, ... }
1482
+ * ```
1483
+ */
1484
+ declare function getAllCustomScalars(): Map<string, typeof CustomScalar>;
1485
+
1486
+ /**
1487
+ * Observer authoring API for FraiseQL event-driven workflows.
1488
+ *
1489
+ * Observers watch for database changes and trigger actions (webhooks, Slack, email).
1490
+ * NO runtime behavior - only used for schema compilation.
1491
+ *
1492
+ * @example
1493
+ * ```typescript
1494
+ * import { Observer, webhook, slack } from "fraiseql";
1495
+ *
1496
+ * class Observers {
1497
+ * @Observer({ entity: "Order", event: "INSERT", actions: [webhook("https://...")] })
1498
+ * onOrderCreated() {}
1499
+ * }
1500
+ * ```
1501
+ */
1502
+
1503
+ /**
1504
+ * Retry configuration for observer actions.
1505
+ */
1506
+ type RetryConfig = ObserverRetryConfig;
1507
+ /**
1508
+ * Default retry configuration used when no retry is specified.
1509
+ */
1510
+ declare const DEFAULT_RETRY_CONFIG: RetryConfig;
1511
+ /**
1512
+ * Configuration for the @Observer decorator.
1513
+ */
1514
+ interface ObserverConfig {
1515
+ entity: string;
1516
+ event: string;
1517
+ actions: ObserverAction[];
1518
+ condition?: string;
1519
+ retry?: RetryConfig;
1520
+ }
1521
+ /**
1522
+ * Method decorator to register an observer with the schema registry.
1523
+ *
1524
+ * @param config - Observer configuration
1525
+ * @returns Method decorator
1526
+ */
1527
+ declare function Observer(config: ObserverConfig): (_target: any, propertyKey: string, _descriptor: PropertyDescriptor) => void;
1528
+ /**
1529
+ * Options for the webhook action factory.
1530
+ */
1531
+ interface WebhookOptions {
1532
+ url_env?: string;
1533
+ headers?: Record<string, string>;
1534
+ body_template?: string;
1535
+ }
1536
+ /**
1537
+ * Create a webhook action.
1538
+ *
1539
+ * @param url - Static URL (mutually exclusive with url_env)
1540
+ * @param options - Additional options including url_env, headers, body_template
1541
+ * @returns Webhook action definition
1542
+ * @throws If neither url nor url_env is provided
1543
+ */
1544
+ declare function webhook(url?: string, options?: WebhookOptions): ObserverAction;
1545
+ /**
1546
+ * Options for the slack action factory.
1547
+ */
1548
+ interface SlackOptions {
1549
+ webhook_url?: string;
1550
+ webhook_url_env?: string;
1551
+ }
1552
+ /**
1553
+ * Create a Slack notification action.
1554
+ *
1555
+ * @param channel - Slack channel (e.g. "#orders")
1556
+ * @param message - Message template with {field} placeholders
1557
+ * @param options - Optional webhook URL or environment variable override
1558
+ * @returns Slack action definition
1559
+ */
1560
+ declare function slack(channel: string, message: string, options?: SlackOptions): ObserverAction;
1561
+ /**
1562
+ * Options for the email action factory.
1563
+ */
1564
+ interface EmailOptions {
1565
+ from_email?: string;
1566
+ }
1567
+ /**
1568
+ * Create an email notification action.
1569
+ *
1570
+ * @param to - Recipient email address
1571
+ * @param subject - Email subject template with {field} placeholders
1572
+ * @param body - Email body template with {field} placeholders
1573
+ * @param options - Optional sender override
1574
+ * @returns Email action definition
1575
+ */
1576
+ declare function email(to: string, subject: string, body: string, options?: EmailOptions): ObserverAction;
1577
+
1578
+ /**
1579
+ * Error hierarchy for FraiseQL HTTP client.
1580
+ */
1581
+ declare class FraiseQLError extends Error {
1582
+ constructor(message: string, options?: ErrorOptions);
1583
+ }
1584
+ interface GraphQLErrorEntry {
1585
+ message: string;
1586
+ locations?: Array<{
1587
+ line: number;
1588
+ column: number;
1589
+ }>;
1590
+ path?: Array<string | number>;
1591
+ extensions?: Record<string, unknown>;
1592
+ }
1593
+ declare class GraphQLError extends FraiseQLError {
1594
+ readonly errors: GraphQLErrorEntry[];
1595
+ constructor(errors: GraphQLErrorEntry[]);
1596
+ }
1597
+ declare class NetworkError extends FraiseQLError {
1598
+ constructor(message: string, options?: ErrorOptions);
1599
+ }
1600
+ declare class TimeoutError extends NetworkError {
1601
+ constructor(message?: string);
1602
+ }
1603
+ declare class AuthenticationError extends FraiseQLError {
1604
+ readonly statusCode: 401 | 403;
1605
+ constructor(statusCode: 401 | 403);
1606
+ }
1607
+ declare class RateLimitError extends FraiseQLError {
1608
+ readonly retryAfterMs?: number;
1609
+ constructor(retryAfterMs?: number);
1610
+ }
1611
+
1612
+ /**
1613
+ * Retry logic for FraiseQL HTTP client operations.
1614
+ */
1615
+
1616
+ interface HttpRetryConfig {
1617
+ maxAttempts?: number;
1618
+ baseDelayMs?: number;
1619
+ maxDelayMs?: number;
1620
+ jitter?: boolean;
1621
+ retryOn?: Array<new (...args: never[]) => FraiseQLError>;
1622
+ onRetry?: (attempt: number, error: FraiseQLError) => void;
1623
+ }
1624
+ declare function executeWithRetry<T>(fn: () => Promise<T>, config?: HttpRetryConfig): Promise<T>;
1625
+
1626
+ /**
1627
+ * FraiseQL HTTP client for executing GraphQL queries and mutations.
1628
+ */
1629
+
1630
+ interface FraiseQLClientConfig {
1631
+ url: string;
1632
+ authorization?: string | (() => string | Promise<string>);
1633
+ timeoutMs?: number;
1634
+ retry?: HttpRetryConfig;
1635
+ headers?: Record<string, string>;
1636
+ fetch?: typeof fetch;
1637
+ }
1638
+ declare class FraiseQLClient {
1639
+ private readonly url;
1640
+ private readonly authorization?;
1641
+ private readonly timeoutMs;
1642
+ private readonly retry;
1643
+ private readonly extraHeaders;
1644
+ private readonly fetchFn;
1645
+ constructor(urlOrConfig: string | FraiseQLClientConfig);
1646
+ private resolveAuth;
1647
+ private buildHeaders;
1648
+ private executeRequest;
1649
+ query<T = Record<string, unknown>>(query: string, variables?: Record<string, unknown>, operationName?: string): Promise<T>;
1650
+ mutate<T = Record<string, unknown>>(mutation: string, variables?: Record<string, unknown>, operationName?: string): Promise<T>;
1651
+ }
1652
+
1653
+ /**
1654
+ * FraiseQL v2 - TypeScript Schema Authoring.
1655
+ *
1656
+ * This module provides decorators for defining GraphQL schemas that are compiled
1657
+ * by the FraiseQL Rust engine. NO runtime FFI - decorators output JSON only.
1658
+ *
1659
+ * Architecture:
1660
+ * TypeScript @decorators → schema.json → fraiseql-cli → schema.compiled.json → Rust runtime
1661
+ *
1662
+ * @example
1663
+ * ```typescript
1664
+ * import * as fraiseql from "fraiseql";
1665
+ *
1666
+ * @fraiseql.Type()
1667
+ * class User {
1668
+ * id: number;
1669
+ * name: string;
1670
+ * email: string;
1671
+ * }
1672
+ *
1673
+ * @fraiseql.Query({ sqlSource: "v_user" })
1674
+ * function users(limit: number = 10): User[] {
1675
+ * // Function body not executed - only for type/metadata
1676
+ * }
1677
+ *
1678
+ * // Export minimal types.json (use fraiseql.toml for queries, security, etc.)
1679
+ * if (require.main === module) {
1680
+ * fraiseql.exportTypes("types.json");
1681
+ * }
1682
+ * ```
1683
+ *
1684
+ * @packageDocumentation
1685
+ */
1686
+ declare const version = "2.0.0-alpha.1";
1687
+
1688
+ export { type APIKey, type AirportCode, type ArgumentDefinition, type ArgumentInfo, AuthenticationError, type CIDR, type CUSIP, type Color, type ContainerNumber, type Coordinates, type CountryCode, type CurrencyCode, CustomScalar, DEFAULT_RETRY_CONFIG, type Date, type DateRange, type DateTime, type Decimal, type DomainName, type Duration, type Email, type EnumConfig, type EnumDefinition, type EnumValue, type ExchangeCode, type ExchangeRate, type Field, type FieldInfo, type FieldMetadata, type File, type FlightNumber, FraiseQLClient, type FraiseQLClientConfig, FraiseQLError, type FunctionSignature, GraphQLError, type GraphQLErrorEntry, type HTML, type HashSHA256, type Hostname, type HttpRetryConfig, type IBAN, type ID, type IPAddress, type IPv4, type IPv6, type ISIN, type Image, type InputConfig, type InputTypeDefinition, type InterfaceConfig, type InterfaceDefinition, type Json, type LEI, type LTree, type LanguageCode, type Latitude, type LicensePlate, type LocaleCode, type Longitude, type MACAddress, type MIC, type Markdown, type MimeType, type Money, Mutation, type MutationConfig, type MutationDefinition, NetworkError, Observer, type OperationConfig, type Percentage, type PhoneNumber, type Port, type PortCode, type PostalCode, Query, type QueryDefinition, RateLimitError, type RetryConfig, type ReturnTypeInfo, SCALAR_NAMES, type SEDOL, Scalar, ScalarValidationError, type Schema, SchemaRegistry, type SemanticVersion, type Slug, type StockSymbol, Subscription, type SubscriptionConfig, type SubscriptionDefinition, type Time, TimeoutError, type Timezone, type TrackingNumber, Type, type TypeConfig, type TypeDefinition, type URL, type UUID, type UnionConfig, type UnionDefinition, type VIN, type Vector, config, email, enum_, executeWithRetry, exportSchema, exportSchemaToString, exportTypes, extractFieldInfo, extractFunctionSignature, field, generateCrudOperations, getAllCustomScalars, getSchemaDict, input, interface_, isScalarType, registerMutation, registerQuery, registerSubscription, registerTypeFields, slack, typeToGraphQL, union, validateCustomScalar, version, webhook };