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.
package/dist/index.js ADDED
@@ -0,0 +1,1345 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ AuthenticationError: () => AuthenticationError,
34
+ CustomScalar: () => CustomScalar,
35
+ DEFAULT_RETRY_CONFIG: () => DEFAULT_RETRY_CONFIG,
36
+ FraiseQLClient: () => FraiseQLClient,
37
+ FraiseQLError: () => FraiseQLError,
38
+ GraphQLError: () => GraphQLError,
39
+ Mutation: () => Mutation,
40
+ NetworkError: () => NetworkError,
41
+ Observer: () => Observer,
42
+ Query: () => Query,
43
+ RateLimitError: () => RateLimitError,
44
+ SCALAR_NAMES: () => SCALAR_NAMES,
45
+ Scalar: () => Scalar,
46
+ ScalarValidationError: () => ScalarValidationError,
47
+ SchemaRegistry: () => SchemaRegistry,
48
+ Subscription: () => Subscription,
49
+ TimeoutError: () => TimeoutError,
50
+ Type: () => Type,
51
+ config: () => config,
52
+ email: () => email,
53
+ enum_: () => enum_,
54
+ executeWithRetry: () => executeWithRetry,
55
+ exportSchema: () => exportSchema,
56
+ exportSchemaToString: () => exportSchemaToString,
57
+ exportTypes: () => exportTypes,
58
+ extractFieldInfo: () => extractFieldInfo,
59
+ extractFunctionSignature: () => extractFunctionSignature,
60
+ field: () => field,
61
+ generateCrudOperations: () => generateCrudOperations,
62
+ getAllCustomScalars: () => getAllCustomScalars,
63
+ getSchemaDict: () => getSchemaDict,
64
+ input: () => input,
65
+ interface_: () => interface_,
66
+ isScalarType: () => isScalarType,
67
+ registerMutation: () => registerMutation,
68
+ registerQuery: () => registerQuery,
69
+ registerSubscription: () => registerSubscription,
70
+ registerTypeFields: () => registerTypeFields,
71
+ slack: () => slack,
72
+ typeToGraphQL: () => typeToGraphQL,
73
+ union: () => union,
74
+ validateCustomScalar: () => validateCustomScalar,
75
+ version: () => version,
76
+ webhook: () => webhook
77
+ });
78
+ module.exports = __toCommonJS(index_exports);
79
+
80
+ // src/scalars.ts
81
+ var CustomScalar = class {
82
+ };
83
+ var SCALAR_NAMES = /* @__PURE__ */ new Set([
84
+ // Core
85
+ "ID",
86
+ "UUID",
87
+ "Json",
88
+ "Decimal",
89
+ "Vector",
90
+ // Date/Time
91
+ "DateTime",
92
+ "Date",
93
+ "Time",
94
+ "DateRange",
95
+ "Duration",
96
+ // Contact/Communication
97
+ "Email",
98
+ "PhoneNumber",
99
+ "URL",
100
+ "DomainName",
101
+ "Hostname",
102
+ // Location/Address
103
+ "PostalCode",
104
+ "Latitude",
105
+ "Longitude",
106
+ "Coordinates",
107
+ "Timezone",
108
+ "LocaleCode",
109
+ "LanguageCode",
110
+ "CountryCode",
111
+ // Financial
112
+ "IBAN",
113
+ "CUSIP",
114
+ "ISIN",
115
+ "SEDOL",
116
+ "LEI",
117
+ "MIC",
118
+ "CurrencyCode",
119
+ "Money",
120
+ "ExchangeCode",
121
+ "ExchangeRate",
122
+ "StockSymbol",
123
+ "Percentage",
124
+ // Identifiers
125
+ "Slug",
126
+ "SemanticVersion",
127
+ "HashSHA256",
128
+ "APIKey",
129
+ "LicensePlate",
130
+ "VIN",
131
+ "TrackingNumber",
132
+ "ContainerNumber",
133
+ // Networking
134
+ "IPAddress",
135
+ "IPv4",
136
+ "IPv6",
137
+ "MACAddress",
138
+ "CIDR",
139
+ "Port",
140
+ // Transportation
141
+ "AirportCode",
142
+ "PortCode",
143
+ "FlightNumber",
144
+ // Content
145
+ "Markdown",
146
+ "HTML",
147
+ "MimeType",
148
+ "Color",
149
+ "Image",
150
+ "File",
151
+ // Database
152
+ "LTree"
153
+ ]);
154
+ function isScalarType(typeName) {
155
+ return SCALAR_NAMES.has(typeName);
156
+ }
157
+
158
+ // src/types.ts
159
+ function typeToGraphQL(type) {
160
+ if (type === null || type === void 0) {
161
+ throw new Error("Cannot convert null or undefined type");
162
+ }
163
+ const typeStr = String(type);
164
+ if (type === String || typeStr === "String") {
165
+ return ["String", false];
166
+ }
167
+ if (type === Number || typeStr === "Number") {
168
+ return ["Float", false];
169
+ }
170
+ if (type === Boolean || typeStr === "Boolean") {
171
+ return ["Boolean", false];
172
+ }
173
+ if (typeof type === "function") {
174
+ return [type.name || "Object", false];
175
+ }
176
+ if (typeof type === "string") {
177
+ if (type.includes(" | null")) {
178
+ const baseType = type.replace(" | null", "").trim();
179
+ return [baseType, true];
180
+ }
181
+ if (type.endsWith("[]")) {
182
+ const elementType = type.slice(0, -2);
183
+ return [`[${elementType}!]`, false];
184
+ }
185
+ if (isScalarType(type)) {
186
+ return [type, false];
187
+ }
188
+ return [type, false];
189
+ }
190
+ throw new Error(`Unsupported type: ${type}`);
191
+ }
192
+ function extractFieldInfo(fields) {
193
+ const result = {};
194
+ for (const [fieldName, fieldType] of Object.entries(fields)) {
195
+ const [graphqlType, nullable] = typeToGraphQL(fieldType);
196
+ result[fieldName] = {
197
+ type: graphqlType,
198
+ nullable
199
+ };
200
+ }
201
+ return result;
202
+ }
203
+ function extractFunctionSignature(_name, params, returnType) {
204
+ const args = [];
205
+ for (const [paramName, paramType] of Object.entries(params)) {
206
+ if (paramName === "self" || paramName === "info") {
207
+ continue;
208
+ }
209
+ const [graphqlType, nullable] = typeToGraphQL(paramType);
210
+ args.push({
211
+ name: paramName,
212
+ type: graphqlType,
213
+ nullable
214
+ });
215
+ }
216
+ const [returnTypeStr, returnNullable] = typeToGraphQL(returnType);
217
+ const isList = returnTypeStr.startsWith("[") && returnTypeStr.endsWith("]");
218
+ return {
219
+ arguments: args,
220
+ returnType: {
221
+ type: returnTypeStr,
222
+ nullable: returnNullable,
223
+ isList
224
+ }
225
+ };
226
+ }
227
+
228
+ // src/registry.ts
229
+ var VALID_REST_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
230
+ function normaliseConfig(config2) {
231
+ const keyMap = {
232
+ sqlSource: "sql_source",
233
+ autoParams: "auto_params",
234
+ jsonbColumn: "jsonb_column",
235
+ cacheTtlSeconds: "cache_ttl_seconds",
236
+ invalidatesViews: "invalidates_views",
237
+ invalidatesFactTables: "invalidates_fact_tables",
238
+ relayCursorColumn: "relay_cursor_column",
239
+ relayCursorType: "relay_cursor_type",
240
+ requiresRole: "requires_role",
241
+ additionalViews: "additional_views"
242
+ };
243
+ const hasRestPath = "restPath" in config2 && config2.restPath != null;
244
+ const hasRestMethod = "restMethod" in config2 && config2.restMethod != null;
245
+ if (hasRestMethod && !hasRestPath) {
246
+ throw new Error("restMethod requires restPath to be set");
247
+ }
248
+ if (hasRestMethod) {
249
+ const method = String(config2.restMethod).toUpperCase();
250
+ if (!VALID_REST_METHODS.has(method)) {
251
+ throw new Error(
252
+ `Invalid REST method '${config2.restMethod}'. Must be one of: ${[...VALID_REST_METHODS].join(", ")}`
253
+ );
254
+ }
255
+ }
256
+ const result = {};
257
+ for (const [key, value] of Object.entries(config2)) {
258
+ if (key === "restPath" || key === "restMethod") {
259
+ continue;
260
+ } else if (key === "inject" && value !== null && typeof value === "object") {
261
+ const injected = {};
262
+ for (const [param, spec] of Object.entries(value)) {
263
+ const colonIdx = spec.indexOf(":");
264
+ if (colonIdx > 0) {
265
+ injected[param] = { source: spec.slice(0, colonIdx), claim: spec.slice(colonIdx + 1) };
266
+ }
267
+ }
268
+ result["inject_params"] = injected;
269
+ } else if (key === "deprecated" && typeof value === "string") {
270
+ result["deprecation"] = { reason: value };
271
+ } else {
272
+ result[keyMap[key] ?? key] = value;
273
+ }
274
+ }
275
+ if (hasRestPath) {
276
+ const method = hasRestMethod ? String(config2.restMethod).toUpperCase() : void 0;
277
+ result["rest"] = {
278
+ path: config2.restPath,
279
+ method
280
+ };
281
+ }
282
+ return result;
283
+ }
284
+ var SchemaRegistry = class {
285
+ static types = /* @__PURE__ */ new Map();
286
+ static queries = /* @__PURE__ */ new Map();
287
+ static mutations = /* @__PURE__ */ new Map();
288
+ static subscriptions = /* @__PURE__ */ new Map();
289
+ static enums = /* @__PURE__ */ new Map();
290
+ static interfaces = /* @__PURE__ */ new Map();
291
+ static inputTypes = /* @__PURE__ */ new Map();
292
+ static unions = /* @__PURE__ */ new Map();
293
+ static factTables = /* @__PURE__ */ new Map();
294
+ static aggregateQueries = /* @__PURE__ */ new Map();
295
+ static observers = /* @__PURE__ */ new Map();
296
+ static customScalars = /* @__PURE__ */ new Map();
297
+ /**
298
+ * Register a GraphQL type.
299
+ *
300
+ * @param name - Type name (e.g., "User")
301
+ * @param fields - List of field definitions
302
+ * @param description - Optional type description
303
+ * @param options - Additional type options
304
+ */
305
+ static registerType(name, fields, description, options) {
306
+ if (this.types.has(name)) {
307
+ throw new Error(
308
+ `Type '${name}' is already registered. Each name must be unique within a schema.`
309
+ );
310
+ }
311
+ const typeDef = { name, fields, description };
312
+ if (options?.relay) typeDef.relay = true;
313
+ if (options?.sqlSource) typeDef.sql_source = options.sqlSource;
314
+ if (options?.jsonbColumn) typeDef.jsonb_column = options.jsonbColumn;
315
+ if (options?.isError) typeDef.is_error = true;
316
+ if (options?.requiresRole) typeDef.requires_role = options.requiresRole;
317
+ if (options?.implements) typeDef.implements = options.implements;
318
+ this.types.set(name, typeDef);
319
+ }
320
+ /**
321
+ * Register a GraphQL query.
322
+ *
323
+ * @param name - Query name
324
+ * @param returnType - Return type name
325
+ * @param returnsList - Whether query returns a list
326
+ * @param nullable - Whether result can be null
327
+ * @param args - List of argument definitions
328
+ * @param description - Optional query description
329
+ * @param config - Additional configuration (sql_source, etc.)
330
+ */
331
+ static registerQuery(name, returnType, returnsList, nullable, args, description, config2) {
332
+ if (this.queries.has(name)) {
333
+ throw new Error(
334
+ `Query '${name}' is already registered. Each name must be unique within a schema.`
335
+ );
336
+ }
337
+ const cleanType = returnsList ? returnType.replace(/[[\]!]/g, "") : returnType;
338
+ if (config2?.relay) {
339
+ if (!returnsList) {
340
+ throw new Error(
341
+ `registerQuery('${name}'): relay: true requires returns_list to be true. Relay connections only apply to list queries.`
342
+ );
343
+ }
344
+ if (!config2.sqlSource) {
345
+ throw new Error(
346
+ `registerQuery('${name}'): relay: true requires sqlSource to be set. The compiler needs the view name to derive the cursor column.`
347
+ );
348
+ }
349
+ if (config2.autoParams) {
350
+ const ap = { ...config2.autoParams };
351
+ delete ap["limit"];
352
+ delete ap["offset"];
353
+ config2 = { ...config2, autoParams: ap };
354
+ }
355
+ }
356
+ const normalisedConfig = config2 ? normaliseConfig(config2) : void 0;
357
+ if (normalisedConfig?.rest) {
358
+ const rest = normalisedConfig.rest;
359
+ if (!rest.method) {
360
+ rest.method = "GET";
361
+ }
362
+ }
363
+ this.queries.set(name, {
364
+ name,
365
+ return_type: cleanType,
366
+ returns_list: returnsList,
367
+ nullable,
368
+ arguments: args,
369
+ description,
370
+ ...normalisedConfig
371
+ });
372
+ }
373
+ /**
374
+ * Register a GraphQL mutation.
375
+ *
376
+ * @param name - Mutation name
377
+ * @param returnType - Return type name
378
+ * @param returnsList - Whether mutation returns a list
379
+ * @param nullable - Whether result can be null
380
+ * @param args - List of argument definitions
381
+ * @param description - Optional mutation description
382
+ * @param config - Additional configuration (sql_source, operation, etc.)
383
+ */
384
+ static registerMutation(name, returnType, returnsList, nullable, args, description, config2) {
385
+ if (this.mutations.has(name)) {
386
+ throw new Error(
387
+ `Mutation '${name}' is already registered. Each name must be unique within a schema.`
388
+ );
389
+ }
390
+ const cleanType = returnsList ? returnType.replace(/[[\]!]/g, "") : returnType;
391
+ const normalisedConfig = config2 ? normaliseConfig(config2) : void 0;
392
+ if (normalisedConfig?.rest) {
393
+ const rest = normalisedConfig.rest;
394
+ if (!rest.method) {
395
+ rest.method = "POST";
396
+ }
397
+ }
398
+ this.mutations.set(name, {
399
+ name,
400
+ return_type: cleanType,
401
+ returns_list: returnsList,
402
+ nullable,
403
+ arguments: args,
404
+ description,
405
+ ...normalisedConfig
406
+ });
407
+ }
408
+ /**
409
+ * Register a GraphQL subscription.
410
+ *
411
+ * Subscriptions in FraiseQL are compiled projections of database events.
412
+ * They are sourced from LISTEN/NOTIFY or CDC, not resolver-based.
413
+ *
414
+ * @param name - Subscription name
415
+ * @param entityType - Entity type name being subscribed to
416
+ * @param nullable - Whether result can be null
417
+ * @param args - List of argument definitions (filters)
418
+ * @param description - Optional subscription description
419
+ * @param config - Additional configuration (topic, operation, etc.)
420
+ */
421
+ static registerSubscription(name, entityType, nullable, args, description, config2) {
422
+ if (this.subscriptions.has(name)) {
423
+ throw new Error(
424
+ `Subscription '${name}' is already registered. Each name must be unique within a schema.`
425
+ );
426
+ }
427
+ this.subscriptions.set(name, {
428
+ name,
429
+ entity_type: entityType,
430
+ nullable,
431
+ arguments: args,
432
+ description,
433
+ ...config2
434
+ });
435
+ }
436
+ /**
437
+ * Register a fact table definition.
438
+ *
439
+ * @param tableName - Fact table name
440
+ * @param measures - List of measure definitions
441
+ * @param dimensions - Dimension metadata
442
+ * @param denormalizedFilters - List of denormalized filter definitions
443
+ */
444
+ static registerFactTable(tableName, measures, dimensions, denormalizedFilters) {
445
+ this.factTables.set(tableName, {
446
+ table_name: tableName,
447
+ measures,
448
+ dimensions,
449
+ denormalized_filters: denormalizedFilters
450
+ });
451
+ }
452
+ /**
453
+ * Register an aggregate query definition.
454
+ *
455
+ * @param name - Query name
456
+ * @param factTable - Fact table name
457
+ * @param autoGroupBy - Auto-generate groupBy fields
458
+ * @param autoAggregates - Auto-generate aggregate fields
459
+ * @param description - Optional query description
460
+ */
461
+ static registerAggregateQuery(name, factTable, autoGroupBy, autoAggregates, description) {
462
+ this.aggregateQueries.set(name, {
463
+ name,
464
+ fact_table: factTable,
465
+ auto_group_by: autoGroupBy,
466
+ auto_aggregates: autoAggregates,
467
+ description
468
+ });
469
+ }
470
+ /**
471
+ * Register an observer.
472
+ *
473
+ * @param name - Observer function name
474
+ * @param entity - Entity type to observe
475
+ * @param event - Event type (INSERT, UPDATE, or DELETE)
476
+ * @param actions - List of action configurations
477
+ * @param condition - Optional condition expression
478
+ * @param retry - Retry configuration
479
+ */
480
+ static registerObserver(name, entity, event, actions, condition, retry) {
481
+ this.observers.set(name, {
482
+ name,
483
+ entity,
484
+ event: event.toUpperCase(),
485
+ actions,
486
+ condition,
487
+ retry: retry || {
488
+ max_attempts: 3,
489
+ backoff_strategy: "exponential",
490
+ initial_delay_ms: 100,
491
+ max_delay_ms: 6e4
492
+ }
493
+ });
494
+ }
495
+ /**
496
+ * Register a GraphQL enum type.
497
+ *
498
+ * @param name - Enum name (e.g., "OrderStatus")
499
+ * @param values - List of enum value definitions
500
+ * @param description - Optional enum description
501
+ */
502
+ static registerEnum(name, values, description) {
503
+ if (this.enums.has(name)) {
504
+ throw new Error(
505
+ `Enum '${name}' is already registered. Each name must be unique within a schema.`
506
+ );
507
+ }
508
+ this.enums.set(name, {
509
+ name,
510
+ values,
511
+ description
512
+ });
513
+ }
514
+ /**
515
+ * Register a GraphQL interface type.
516
+ *
517
+ * @param name - Interface name (e.g., "Node")
518
+ * @param fields - List of field definitions
519
+ * @param description - Optional interface description
520
+ */
521
+ static registerInterface(name, fields, description) {
522
+ if (this.interfaces.has(name)) {
523
+ throw new Error(
524
+ `Interface '${name}' is already registered. Each name must be unique within a schema.`
525
+ );
526
+ }
527
+ this.interfaces.set(name, {
528
+ name,
529
+ fields,
530
+ description
531
+ });
532
+ }
533
+ /**
534
+ * Register a GraphQL input type.
535
+ *
536
+ * @param name - Input type name (e.g., "CreateUserInput")
537
+ * @param fields - List of field definitions with optional defaults
538
+ * @param description - Optional input type description
539
+ */
540
+ static registerInputType(name, fields, description) {
541
+ if (this.inputTypes.has(name)) {
542
+ throw new Error(
543
+ `Input type '${name}' is already registered. Each name must be unique within a schema.`
544
+ );
545
+ }
546
+ this.inputTypes.set(name, {
547
+ name,
548
+ fields,
549
+ description
550
+ });
551
+ }
552
+ /**
553
+ * Register a GraphQL union type.
554
+ *
555
+ * @param name - Union name (e.g., "SearchResult")
556
+ * @param memberTypes - List of member type names
557
+ * @param description - Optional union description
558
+ */
559
+ static registerUnion(name, memberTypes, description) {
560
+ if (this.unions.has(name)) {
561
+ throw new Error(
562
+ `Union '${name}' is already registered. Each name must be unique within a schema.`
563
+ );
564
+ }
565
+ this.unions.set(name, {
566
+ name,
567
+ member_types: memberTypes,
568
+ description
569
+ });
570
+ }
571
+ /**
572
+ * Register a custom scalar.
573
+ *
574
+ * @param name - Scalar name (e.g., "Email")
575
+ * @param scalarClass - The CustomScalar subclass
576
+ * @param description - Optional scalar description
577
+ *
578
+ * @throws If scalar name is not unique
579
+ */
580
+ static registerScalar(name, scalarClass, description) {
581
+ if (this.customScalars.has(name)) {
582
+ throw new Error(
583
+ `Scalar '${name}' is already registered. Each name must be unique within a schema.`
584
+ );
585
+ }
586
+ this.customScalars.set(name, { class: scalarClass, description });
587
+ }
588
+ /**
589
+ * Get all registered custom scalars.
590
+ *
591
+ * @returns Map of scalar names to CustomScalar classes
592
+ */
593
+ static getCustomScalars() {
594
+ const result = /* @__PURE__ */ new Map();
595
+ for (const [name, { class: scalarClass }] of this.customScalars) {
596
+ result.set(name, scalarClass);
597
+ }
598
+ return result;
599
+ }
600
+ /**
601
+ * Get the complete schema as an object.
602
+ *
603
+ * @returns Schema object with types, queries, mutations, subscriptions, and analytics sections
604
+ */
605
+ static getSchema() {
606
+ const schema = {
607
+ types: Array.from(this.types.values()),
608
+ queries: Array.from(this.queries.values()),
609
+ mutations: Array.from(this.mutations.values()),
610
+ subscriptions: Array.from(this.subscriptions.values())
611
+ };
612
+ if (this.enums.size > 0) {
613
+ schema.enums = Array.from(this.enums.values());
614
+ }
615
+ if (this.interfaces.size > 0) {
616
+ schema.interfaces = Array.from(this.interfaces.values());
617
+ }
618
+ if (this.inputTypes.size > 0) {
619
+ schema.input_types = Array.from(this.inputTypes.values());
620
+ }
621
+ if (this.unions.size > 0) {
622
+ schema.unions = Array.from(this.unions.values());
623
+ }
624
+ if (this.factTables.size > 0) {
625
+ schema.fact_tables = Array.from(this.factTables.values());
626
+ }
627
+ if (this.aggregateQueries.size > 0) {
628
+ schema.aggregate_queries = Array.from(this.aggregateQueries.values());
629
+ }
630
+ if (this.observers.size > 0) {
631
+ schema.observers = Array.from(this.observers.values());
632
+ }
633
+ if (this.customScalars.size > 0) {
634
+ const customScalars = {};
635
+ for (const [name, { class: scalarClass, description }] of this.customScalars) {
636
+ customScalars[name] = {
637
+ name,
638
+ description: description ?? "Custom scalar",
639
+ validate: true
640
+ };
641
+ void scalarClass;
642
+ }
643
+ schema.customScalars = customScalars;
644
+ }
645
+ return schema;
646
+ }
647
+ /**
648
+ * Clear the registry (useful for testing).
649
+ */
650
+ static clear() {
651
+ this.types.clear();
652
+ this.queries.clear();
653
+ this.mutations.clear();
654
+ this.subscriptions.clear();
655
+ this.enums.clear();
656
+ this.interfaces.clear();
657
+ this.inputTypes.clear();
658
+ this.unions.clear();
659
+ this.factTables.clear();
660
+ this.aggregateQueries.clear();
661
+ this.observers.clear();
662
+ this.customScalars.clear();
663
+ }
664
+ };
665
+
666
+ // src/crud.ts
667
+ var ALL_OPS = /* @__PURE__ */ new Set(["read", "create", "update", "delete"]);
668
+ function pascalToSnake(name) {
669
+ return name.replace(/(?<!^)([A-Z])/g, "_$1").toLowerCase();
670
+ }
671
+ function pluralize(name) {
672
+ if (name.endsWith("s") && !name.endsWith("ss")) return name;
673
+ for (const suffix of ["ss", "sh", "ch", "x", "z"]) {
674
+ if (name.endsWith(suffix)) return name + "es";
675
+ }
676
+ if (/[^aeiou]y$/.test(name)) return name.slice(0, -1) + "ies";
677
+ return name + "s";
678
+ }
679
+ function parseCrudOps(crud) {
680
+ if (crud === true) return new Set(ALL_OPS);
681
+ if (Array.isArray(crud)) {
682
+ const unknown = crud.filter((op) => !ALL_OPS.has(op));
683
+ if (unknown.length > 0) {
684
+ throw new Error(
685
+ `Unknown CRUD operations: ${unknown.join(", ")}. Valid: read, create, update, delete`
686
+ );
687
+ }
688
+ return new Set(crud);
689
+ }
690
+ return /* @__PURE__ */ new Set();
691
+ }
692
+ function generateCrudOperations(typeName, fields, crud, sqlSource, cascade) {
693
+ const ops = parseCrudOps(crud);
694
+ if (ops.size === 0) return;
695
+ if (fields.length === 0) {
696
+ throw new Error(`Type '${typeName}' has no fields; cannot generate CRUD operations`);
697
+ }
698
+ const snake = pascalToSnake(typeName);
699
+ const view = sqlSource ?? `v_${snake}`;
700
+ const pkField = fields[0];
701
+ if (ops.has("read")) {
702
+ SchemaRegistry.registerQuery(
703
+ snake,
704
+ typeName,
705
+ false,
706
+ true,
707
+ [{ name: pkField.name, type: pkField.type, nullable: false }],
708
+ `Get ${typeName} by ID.`,
709
+ { sql_source: view }
710
+ );
711
+ SchemaRegistry.registerQuery(
712
+ pluralize(snake),
713
+ typeName,
714
+ true,
715
+ false,
716
+ [],
717
+ `List ${typeName} records.`,
718
+ { sql_source: view, auto_params: { where: true, order_by: true, limit: true, offset: true } }
719
+ );
720
+ }
721
+ if (ops.has("create")) {
722
+ const args = fields.map((f) => ({
723
+ name: f.name,
724
+ type: f.type,
725
+ nullable: f.nullable
726
+ }));
727
+ const config2 = {
728
+ sql_source: `fn_create_${snake}`,
729
+ operation: "INSERT"
730
+ };
731
+ if (cascade) config2.cascade = true;
732
+ SchemaRegistry.registerMutation(
733
+ `create_${snake}`,
734
+ typeName,
735
+ false,
736
+ false,
737
+ args,
738
+ `Create a new ${typeName}.`,
739
+ config2
740
+ );
741
+ }
742
+ if (ops.has("update")) {
743
+ const args = [
744
+ { name: pkField.name, type: pkField.type, nullable: false },
745
+ ...fields.slice(1).map((f) => ({ name: f.name, type: f.type, nullable: true }))
746
+ ];
747
+ const config2 = {
748
+ sql_source: `fn_update_${snake}`,
749
+ operation: "UPDATE"
750
+ };
751
+ if (cascade) config2.cascade = true;
752
+ SchemaRegistry.registerMutation(
753
+ `update_${snake}`,
754
+ typeName,
755
+ false,
756
+ true,
757
+ args,
758
+ `Update an existing ${typeName}.`,
759
+ config2
760
+ );
761
+ }
762
+ if (ops.has("delete")) {
763
+ const config2 = {
764
+ sql_source: `fn_delete_${snake}`,
765
+ operation: "DELETE"
766
+ };
767
+ if (cascade) config2.cascade = true;
768
+ SchemaRegistry.registerMutation(
769
+ `delete_${snake}`,
770
+ typeName,
771
+ false,
772
+ false,
773
+ [{ name: pkField.name, type: pkField.type, nullable: false }],
774
+ `Delete a ${typeName}.`,
775
+ config2
776
+ );
777
+ }
778
+ }
779
+
780
+ // src/decorators.ts
781
+ function field(options) {
782
+ return options;
783
+ }
784
+ function Type(_config) {
785
+ return function(constructor) {
786
+ const typeName = constructor.name;
787
+ SchemaRegistry.registerType(typeName, [], _config?.description, {
788
+ sqlSource: _config?.sqlSource
789
+ });
790
+ return constructor;
791
+ };
792
+ }
793
+ function Query(config2) {
794
+ return function(_target, propertyKey, descriptor) {
795
+ const originalMethod = descriptor.value;
796
+ const methodName = propertyKey;
797
+ SchemaRegistry.registerQuery(
798
+ methodName,
799
+ "Query",
800
+ // Placeholder - should be extracted from metadata
801
+ false,
802
+ // Placeholder
803
+ false,
804
+ // Placeholder
805
+ [],
806
+ // Placeholder
807
+ originalMethod?.toString?.().split("\n")[0] ?? void 0,
808
+ config2
809
+ );
810
+ return descriptor;
811
+ };
812
+ }
813
+ function Mutation(config2) {
814
+ return function(_target, propertyKey, descriptor) {
815
+ const originalMethod = descriptor.value;
816
+ const methodName = propertyKey;
817
+ SchemaRegistry.registerMutation(
818
+ methodName,
819
+ "Mutation",
820
+ // Placeholder - should be extracted from metadata
821
+ false,
822
+ // Placeholder
823
+ false,
824
+ // Placeholder
825
+ [],
826
+ // Placeholder
827
+ originalMethod?.toString?.().split("\n")[0] ?? void 0,
828
+ config2
829
+ );
830
+ return descriptor;
831
+ };
832
+ }
833
+ function enum_(name, values, config2) {
834
+ const enumValues = Object.keys(values).map((key) => ({
835
+ name: key
836
+ }));
837
+ SchemaRegistry.registerEnum(name, enumValues, config2?.description);
838
+ return values;
839
+ }
840
+ function interface_(name, fields, config2) {
841
+ SchemaRegistry.registerInterface(name, fields, config2?.description);
842
+ return {};
843
+ }
844
+ function union(name, memberTypes, config2) {
845
+ SchemaRegistry.registerUnion(name, memberTypes, config2?.description);
846
+ return {};
847
+ }
848
+ function input(name, fields, config2) {
849
+ SchemaRegistry.registerInputType(name, fields, config2?.description);
850
+ return {};
851
+ }
852
+ function registerTypeFields(typeName, fields, description, options) {
853
+ SchemaRegistry.registerType(typeName, fields, description, options);
854
+ if (options?.crud) {
855
+ generateCrudOperations(typeName, fields, options.crud, options.sqlSource, options.cascade);
856
+ }
857
+ }
858
+ function registerQuery(name, returnType, returnsList, nullable, args, description, config2) {
859
+ SchemaRegistry.registerQuery(name, returnType, returnsList, nullable, args, description, config2);
860
+ }
861
+ function registerMutation(name, returnType, returnsList, nullable, args, description, config2) {
862
+ SchemaRegistry.registerMutation(
863
+ name,
864
+ returnType,
865
+ returnsList,
866
+ nullable,
867
+ args,
868
+ description,
869
+ config2
870
+ );
871
+ }
872
+ function Subscription(config2) {
873
+ return function(_target, propertyKey, descriptor) {
874
+ const originalMethod = descriptor.value;
875
+ const methodName = propertyKey;
876
+ const entityType = config2?.entityType || "Subscription";
877
+ SchemaRegistry.registerSubscription(
878
+ methodName,
879
+ entityType,
880
+ false,
881
+ // Placeholder for nullable
882
+ [],
883
+ // Placeholder for arguments
884
+ originalMethod?.toString?.().split("\n")[0] ?? void 0,
885
+ config2
886
+ );
887
+ return descriptor;
888
+ };
889
+ }
890
+ function registerSubscription(name, entityType, nullable, args, description, config2) {
891
+ SchemaRegistry.registerSubscription(name, entityType, nullable, args, description, config2);
892
+ }
893
+ function Scalar(target) {
894
+ if (!isCustomScalarSubclass(target)) {
895
+ const name = target.name ?? "(unknown)";
896
+ throw new TypeError(
897
+ `@Scalar can only be applied to CustomScalar subclasses, got ${name}`
898
+ );
899
+ }
900
+ const instance = new target();
901
+ const scalarName = instance.name;
902
+ if (!scalarName || typeof scalarName !== "string") {
903
+ throw new Error(
904
+ `CustomScalar ${target.name} must have a 'name' property of type string`
905
+ );
906
+ }
907
+ SchemaRegistry.registerScalar(scalarName, target, target.toString());
908
+ return target;
909
+ }
910
+ function isCustomScalarSubclass(target) {
911
+ try {
912
+ return target.prototype instanceof CustomScalar || target === CustomScalar;
913
+ } catch {
914
+ return false;
915
+ }
916
+ }
917
+
918
+ // src/schema.ts
919
+ var fs = __toESM(require("fs"));
920
+ var BUILTIN_SCALARS = /* @__PURE__ */ new Set(["String", "Int", "Float", "Boolean", "ID"]);
921
+ function validateSchemaBeforeExport(schema) {
922
+ const registeredTypeNames = /* @__PURE__ */ new Set([
923
+ ...schema.types.map((t) => t.name),
924
+ ...(schema.enums ?? []).map((e) => e.name),
925
+ ...BUILTIN_SCALARS
926
+ ]);
927
+ const errors = [];
928
+ for (const query of schema.queries) {
929
+ const ret = query.return_type;
930
+ if (ret && !registeredTypeNames.has(ret)) {
931
+ errors.push(
932
+ `Query '${query.name}' has return type '${ret}' which is not a registered type.`
933
+ );
934
+ }
935
+ }
936
+ for (const mutation of schema.mutations) {
937
+ const ret = mutation.return_type;
938
+ if (ret && !registeredTypeNames.has(ret)) {
939
+ errors.push(
940
+ `Mutation '${mutation.name}' has return type '${ret}' which is not a registered type.`
941
+ );
942
+ }
943
+ }
944
+ if (errors.length > 0) {
945
+ throw new Error(
946
+ `Schema validation failed before export. Fix the following errors:
947
+ - ${errors.join("\n - ")}`
948
+ );
949
+ }
950
+ }
951
+ var ConfigHolder = class {
952
+ static pendingConfig = null;
953
+ };
954
+ function config(configObj) {
955
+ ConfigHolder.pendingConfig = configObj;
956
+ }
957
+ function exportSchema(outputPath, options = {}) {
958
+ const { pretty = true } = options;
959
+ const schema = SchemaRegistry.getSchema();
960
+ validateSchemaBeforeExport(schema);
961
+ const content = pretty ? JSON.stringify(schema, null, 2) + "\n" : JSON.stringify(schema);
962
+ fs.writeFileSync(outputPath, content, { encoding: "utf-8" });
963
+ console.log(`\u2705 Schema exported to ${outputPath}`);
964
+ console.log(` Types: ${schema.types.length}`);
965
+ console.log(` Queries: ${schema.queries.length}`);
966
+ console.log(` Mutations: ${schema.mutations.length}`);
967
+ if (schema.fact_tables) {
968
+ console.log(` Fact Tables: ${schema.fact_tables.length}`);
969
+ }
970
+ if (schema.aggregate_queries) {
971
+ console.log(` Aggregate Queries: ${schema.aggregate_queries.length}`);
972
+ }
973
+ if (schema.observers) {
974
+ console.log(` Observers: ${schema.observers.length}`);
975
+ }
976
+ }
977
+ function getSchemaDict() {
978
+ return SchemaRegistry.getSchema();
979
+ }
980
+ function exportSchemaToString(options = {}) {
981
+ const { pretty = true } = options;
982
+ const schema = SchemaRegistry.getSchema();
983
+ return pretty ? JSON.stringify(schema, null, 2) : JSON.stringify(schema);
984
+ }
985
+ function exportTypes(outputPath, options = {}) {
986
+ const { pretty = true } = options;
987
+ const fullSchema = SchemaRegistry.getSchema();
988
+ const minimalSchema = {
989
+ types: fullSchema.types || [],
990
+ enums: fullSchema.enums || [],
991
+ input_types: fullSchema.input_types || [],
992
+ interfaces: fullSchema.interfaces || []
993
+ };
994
+ const content = pretty ? JSON.stringify(minimalSchema, null, 2) + "\n" : JSON.stringify(minimalSchema);
995
+ fs.writeFileSync(outputPath, content, { encoding: "utf-8" });
996
+ console.log(`\u2705 Types exported to ${outputPath}`);
997
+ console.log(` Types: ${minimalSchema.types.length}`);
998
+ if (minimalSchema.enums.length > 0) {
999
+ console.log(` Enums: ${minimalSchema.enums.length}`);
1000
+ }
1001
+ if (minimalSchema.input_types.length > 0) {
1002
+ console.log(` Input types: ${minimalSchema.input_types.length}`);
1003
+ }
1004
+ if (minimalSchema.interfaces.length > 0) {
1005
+ console.log(` Interfaces: ${minimalSchema.interfaces.length}`);
1006
+ }
1007
+ console.log(` \u2192 Use with: fraiseql compile fraiseql.toml --types ${outputPath}`);
1008
+ }
1009
+
1010
+ // src/validators.ts
1011
+ var ScalarValidationError = class extends Error {
1012
+ /**
1013
+ * Creates a new ScalarValidationError.
1014
+ *
1015
+ * @param scalarName - Name of the scalar that failed validation
1016
+ * @param context - The validation context ("serialize", "parseValue", or "parseLiteral")
1017
+ * @param message - The underlying error message
1018
+ */
1019
+ constructor(scalarName, context, message) {
1020
+ super(
1021
+ `Scalar ${JSON.stringify(scalarName)} validation failed in ${context}: ${message}`
1022
+ );
1023
+ this.scalarName = scalarName;
1024
+ this.context = context;
1025
+ this.name = "ScalarValidationError";
1026
+ }
1027
+ };
1028
+ function validateCustomScalar(scalarClass, value, context = "parseValue") {
1029
+ const instance = new scalarClass();
1030
+ const scalarName = instance.name;
1031
+ try {
1032
+ switch (context) {
1033
+ case "serialize":
1034
+ return instance.serialize(value);
1035
+ case "parseValue":
1036
+ return instance.parseValue(value);
1037
+ case "parseLiteral":
1038
+ return instance.parseLiteral(value);
1039
+ default:
1040
+ throw new Error(`Unknown validation context: ${context}`);
1041
+ }
1042
+ } catch (error) {
1043
+ if (error instanceof ScalarValidationError) {
1044
+ throw error;
1045
+ }
1046
+ const message = error instanceof Error ? error.message : String(error);
1047
+ throw new ScalarValidationError(scalarName, context, message);
1048
+ }
1049
+ }
1050
+ function getAllCustomScalars() {
1051
+ return SchemaRegistry.getCustomScalars();
1052
+ }
1053
+
1054
+ // src/observers.ts
1055
+ var DEFAULT_RETRY_CONFIG = {
1056
+ max_attempts: 3,
1057
+ backoff_strategy: "exponential",
1058
+ initial_delay_ms: 100,
1059
+ max_delay_ms: 6e4
1060
+ };
1061
+ function Observer(config2) {
1062
+ return function(_target, propertyKey, _descriptor) {
1063
+ SchemaRegistry.registerObserver(
1064
+ propertyKey,
1065
+ config2.entity,
1066
+ config2.event,
1067
+ config2.actions,
1068
+ config2.condition,
1069
+ config2.retry
1070
+ );
1071
+ };
1072
+ }
1073
+ function webhook(url, options) {
1074
+ if (url === void 0 && options?.url_env === void 0) {
1075
+ throw new Error("Either url or url_env must be provided");
1076
+ }
1077
+ const action = {
1078
+ type: "webhook",
1079
+ headers: { "Content-Type": "application/json", ...options?.headers ?? {} }
1080
+ };
1081
+ if (url !== void 0) {
1082
+ action.url = url;
1083
+ }
1084
+ if (options?.url_env !== void 0) {
1085
+ action.url_env = options.url_env;
1086
+ }
1087
+ if (options?.body_template !== void 0) {
1088
+ action.body_template = options.body_template;
1089
+ }
1090
+ return action;
1091
+ }
1092
+ function slack(channel, message, options) {
1093
+ const action = {
1094
+ type: "slack",
1095
+ channel,
1096
+ message,
1097
+ webhook_url_env: options?.webhook_url_env ?? "SLACK_WEBHOOK_URL"
1098
+ };
1099
+ if (options?.webhook_url !== void 0) {
1100
+ action.webhook_url = options.webhook_url;
1101
+ }
1102
+ return action;
1103
+ }
1104
+ function email(to, subject, body, options) {
1105
+ const action = {
1106
+ type: "email",
1107
+ to,
1108
+ subject,
1109
+ body
1110
+ };
1111
+ if (options?.from_email !== void 0) {
1112
+ action.from = options.from_email;
1113
+ }
1114
+ return action;
1115
+ }
1116
+
1117
+ // src/errors.ts
1118
+ var FraiseQLError = class extends Error {
1119
+ constructor(message, options) {
1120
+ super(message, options);
1121
+ this.name = "FraiseQLError";
1122
+ }
1123
+ };
1124
+ var GraphQLError = class extends FraiseQLError {
1125
+ errors;
1126
+ constructor(errors) {
1127
+ super(errors[0]?.message ?? "GraphQL error");
1128
+ this.name = "GraphQLError";
1129
+ this.errors = errors;
1130
+ }
1131
+ };
1132
+ var NetworkError = class extends FraiseQLError {
1133
+ constructor(message, options) {
1134
+ super(message, options);
1135
+ this.name = "NetworkError";
1136
+ }
1137
+ };
1138
+ var TimeoutError = class extends NetworkError {
1139
+ constructor(message = "Request timed out") {
1140
+ super(message);
1141
+ this.name = "TimeoutError";
1142
+ }
1143
+ };
1144
+ var AuthenticationError = class extends FraiseQLError {
1145
+ statusCode;
1146
+ constructor(statusCode) {
1147
+ super(`Authentication failed (HTTP ${statusCode})`);
1148
+ this.name = "AuthenticationError";
1149
+ this.statusCode = statusCode;
1150
+ }
1151
+ };
1152
+ var RateLimitError = class extends FraiseQLError {
1153
+ retryAfterMs;
1154
+ constructor(retryAfterMs) {
1155
+ super("Rate limit exceeded");
1156
+ this.name = "RateLimitError";
1157
+ this.retryAfterMs = retryAfterMs;
1158
+ }
1159
+ };
1160
+
1161
+ // src/http-retry.ts
1162
+ async function executeWithRetry(fn, config2 = {}) {
1163
+ const {
1164
+ maxAttempts = 1,
1165
+ baseDelayMs = 1e3,
1166
+ maxDelayMs = 3e4,
1167
+ jitter = true,
1168
+ retryOn = [NetworkError, TimeoutError],
1169
+ onRetry
1170
+ } = config2;
1171
+ let lastError;
1172
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1173
+ try {
1174
+ return await fn();
1175
+ } catch (error) {
1176
+ if (attempt === maxAttempts) throw error;
1177
+ const isRetryable = retryOn.some(
1178
+ (ErrorClass) => error instanceof ErrorClass
1179
+ );
1180
+ if (!isRetryable) throw error;
1181
+ lastError = error;
1182
+ onRetry?.(attempt, lastError);
1183
+ const delay = Math.min(
1184
+ baseDelayMs * Math.pow(2, attempt - 1),
1185
+ maxDelayMs
1186
+ );
1187
+ const actualDelay = jitter ? delay * (0.5 + Math.random() * 0.5) : delay;
1188
+ await new Promise((resolve) => setTimeout(resolve, actualDelay));
1189
+ }
1190
+ }
1191
+ throw lastError;
1192
+ }
1193
+
1194
+ // src/client.ts
1195
+ var FraiseQLClient = class {
1196
+ url;
1197
+ authorization;
1198
+ timeoutMs;
1199
+ retry;
1200
+ extraHeaders;
1201
+ fetchFn;
1202
+ constructor(urlOrConfig) {
1203
+ const config2 = typeof urlOrConfig === "string" ? { url: urlOrConfig } : urlOrConfig;
1204
+ this.url = config2.url;
1205
+ this.authorization = config2.authorization;
1206
+ this.timeoutMs = config2.timeoutMs ?? 3e4;
1207
+ this.retry = config2.retry ?? {};
1208
+ this.extraHeaders = config2.headers ?? {};
1209
+ this.fetchFn = config2.fetch ?? globalThis.fetch.bind(globalThis);
1210
+ }
1211
+ async resolveAuth() {
1212
+ if (this.authorization === void 0) return void 0;
1213
+ if (typeof this.authorization === "string") return this.authorization;
1214
+ return this.authorization();
1215
+ }
1216
+ async buildHeaders() {
1217
+ const headers = {
1218
+ "Content-Type": "application/json",
1219
+ ...this.extraHeaders
1220
+ };
1221
+ const auth = await this.resolveAuth();
1222
+ if (auth !== void 0) {
1223
+ headers["Authorization"] = auth;
1224
+ }
1225
+ return headers;
1226
+ }
1227
+ async executeRequest(body) {
1228
+ return executeWithRetry(async () => {
1229
+ const controller = new AbortController();
1230
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
1231
+ let response;
1232
+ try {
1233
+ response = await this.fetchFn(this.url, {
1234
+ method: "POST",
1235
+ headers: await this.buildHeaders(),
1236
+ body,
1237
+ signal: controller.signal
1238
+ });
1239
+ } catch (error) {
1240
+ if (error instanceof Error && (error.name === "AbortError" || error.message.toLowerCase().includes("abort"))) {
1241
+ throw new TimeoutError();
1242
+ }
1243
+ throw new NetworkError(
1244
+ error instanceof Error ? error.message : "Network request failed",
1245
+ { cause: error }
1246
+ );
1247
+ } finally {
1248
+ clearTimeout(timer);
1249
+ }
1250
+ if (response.status === 401 || response.status === 403) {
1251
+ throw new AuthenticationError(response.status);
1252
+ }
1253
+ if (response.status === 429) {
1254
+ const retryAfterHeader = response.headers.get("Retry-After");
1255
+ const retryAfterMs = retryAfterHeader ? parseInt(retryAfterHeader, 10) * 1e3 : void 0;
1256
+ throw new RateLimitError(
1257
+ Number.isNaN(retryAfterMs) ? void 0 : retryAfterMs
1258
+ );
1259
+ }
1260
+ if (!response.ok) {
1261
+ throw new NetworkError(
1262
+ `HTTP ${response.status}: ${response.statusText}`
1263
+ );
1264
+ }
1265
+ let json;
1266
+ try {
1267
+ json = await response.json();
1268
+ } catch (error) {
1269
+ throw new NetworkError("Failed to parse JSON response", {
1270
+ cause: error
1271
+ });
1272
+ }
1273
+ if (json.errors !== null && json.errors !== void 0 && json.errors.length > 0) {
1274
+ throw new GraphQLError(json.errors);
1275
+ }
1276
+ return json.data ?? {};
1277
+ }, this.retry);
1278
+ }
1279
+ async query(query, variables, operationName) {
1280
+ const body = JSON.stringify({
1281
+ query,
1282
+ variables,
1283
+ ...operationName && { operationName }
1284
+ });
1285
+ return this.executeRequest(body);
1286
+ }
1287
+ async mutate(mutation, variables, operationName) {
1288
+ const body = JSON.stringify({
1289
+ query: mutation,
1290
+ variables,
1291
+ ...operationName && { operationName }
1292
+ });
1293
+ return this.executeRequest(body);
1294
+ }
1295
+ };
1296
+
1297
+ // src/index.ts
1298
+ var version = "2.0.0-alpha.1";
1299
+ // Annotate the CommonJS export names for ESM import in node:
1300
+ 0 && (module.exports = {
1301
+ AuthenticationError,
1302
+ CustomScalar,
1303
+ DEFAULT_RETRY_CONFIG,
1304
+ FraiseQLClient,
1305
+ FraiseQLError,
1306
+ GraphQLError,
1307
+ Mutation,
1308
+ NetworkError,
1309
+ Observer,
1310
+ Query,
1311
+ RateLimitError,
1312
+ SCALAR_NAMES,
1313
+ Scalar,
1314
+ ScalarValidationError,
1315
+ SchemaRegistry,
1316
+ Subscription,
1317
+ TimeoutError,
1318
+ Type,
1319
+ config,
1320
+ email,
1321
+ enum_,
1322
+ executeWithRetry,
1323
+ exportSchema,
1324
+ exportSchemaToString,
1325
+ exportTypes,
1326
+ extractFieldInfo,
1327
+ extractFunctionSignature,
1328
+ field,
1329
+ generateCrudOperations,
1330
+ getAllCustomScalars,
1331
+ getSchemaDict,
1332
+ input,
1333
+ interface_,
1334
+ isScalarType,
1335
+ registerMutation,
1336
+ registerQuery,
1337
+ registerSubscription,
1338
+ registerTypeFields,
1339
+ slack,
1340
+ typeToGraphQL,
1341
+ union,
1342
+ validateCustomScalar,
1343
+ version,
1344
+ webhook
1345
+ });