@xylex-group/athena 1.7.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,164 @@
1
+ import { a as BackendType, p as IntrospectionSnapshot, o as SchemaIntrospectionProvider } from './types-BnzoaNRC.cjs';
2
+
3
+ /**
4
+ * Supported case transformations for generated symbols and path token variants.
5
+ */
6
+ type NamingStyle = 'preserve' | 'camel' | 'pascal' | 'snake' | 'kebab';
7
+ /**
8
+ * Naming configuration for generated TypeScript identifiers.
9
+ */
10
+ interface GeneratorNamingConfig {
11
+ modelType: NamingStyle;
12
+ modelConst: NamingStyle;
13
+ schemaConst: NamingStyle;
14
+ databaseConst: NamingStyle;
15
+ registryConst: NamingStyle;
16
+ }
17
+ /**
18
+ * Stable feature flags for generator output behavior.
19
+ */
20
+ interface GeneratorFeatureFlags {
21
+ emitRelations: boolean;
22
+ emitRegistry: boolean;
23
+ }
24
+ /**
25
+ * Experimental toggles for optional/forward-compatible generator behavior.
26
+ */
27
+ interface GeneratorExperimentalFlags {
28
+ /**
29
+ * Legacy compatibility toggle from the initial scaffold.
30
+ * Gateway introspection is now implemented; this flag is retained for additive config compatibility.
31
+ */
32
+ postgresGatewayIntrospection: boolean;
33
+ /**
34
+ * Enables contract placeholders for future Scylla provider work.
35
+ */
36
+ scyllaProviderContracts: boolean;
37
+ }
38
+ /**
39
+ * Path templates for each generated artifact category.
40
+ */
41
+ interface GeneratorOutputTargets {
42
+ model: string;
43
+ schema: string;
44
+ database: string;
45
+ registry: string;
46
+ }
47
+ /**
48
+ * Output configuration including dynamic placeholder aliases.
49
+ */
50
+ interface GeneratorOutputConfig {
51
+ targets: GeneratorOutputTargets;
52
+ placeholderMap: Record<string, string>;
53
+ }
54
+ /**
55
+ * Schemas selected for PostgreSQL introspection. Strings may be comma-separated
56
+ * to support env-driven configs such as `process.env.GENERATOR_SCHEMAS`.
57
+ */
58
+ type GeneratorSchemaSelection = string | readonly string[];
59
+ /**
60
+ * Direct PostgreSQL introspection mode (implemented).
61
+ */
62
+ interface PostgresDirectProviderConfig {
63
+ kind: 'postgres';
64
+ mode: 'direct';
65
+ connectionString: string;
66
+ database?: string;
67
+ schemas?: GeneratorSchemaSelection;
68
+ }
69
+ /**
70
+ * Athena gateway-backed PostgreSQL introspection mode using `/gateway/query`.
71
+ */
72
+ interface PostgresGatewayProviderConfig {
73
+ kind: 'postgres';
74
+ mode: 'gateway';
75
+ gatewayUrl: string;
76
+ apiKey: string;
77
+ database: string;
78
+ schemas?: GeneratorSchemaSelection;
79
+ backend?: BackendType;
80
+ }
81
+ /**
82
+ * Scylla introspection provider contract placeholder (phase-two scaffold).
83
+ */
84
+ interface ScyllaDirectProviderConfig {
85
+ kind: 'scylla';
86
+ mode: 'direct';
87
+ contactPoints: string[];
88
+ keyspace: string;
89
+ datacenter?: string;
90
+ }
91
+ type GeneratorProviderConfig = PostgresDirectProviderConfig | PostgresGatewayProviderConfig | ScyllaDirectProviderConfig;
92
+ /**
93
+ * Root config contract loaded from `athena.config.ts`.
94
+ */
95
+ interface AthenaGeneratorConfig {
96
+ provider: GeneratorProviderConfig;
97
+ output: GeneratorOutputConfig;
98
+ naming?: Partial<GeneratorNamingConfig>;
99
+ features?: Partial<GeneratorFeatureFlags>;
100
+ experimental?: Partial<GeneratorExperimentalFlags>;
101
+ }
102
+ /**
103
+ * Normalized generator config with defaults applied.
104
+ */
105
+ interface NormalizedAthenaGeneratorConfig {
106
+ provider: GeneratorProviderConfig;
107
+ output: GeneratorOutputConfig;
108
+ naming: GeneratorNamingConfig;
109
+ features: GeneratorFeatureFlags;
110
+ experimental: GeneratorExperimentalFlags;
111
+ }
112
+ /**
113
+ * Config loader options for CLI/programmatic usage.
114
+ */
115
+ interface LoadGeneratorConfigOptions {
116
+ cwd?: string;
117
+ configPath?: string;
118
+ }
119
+ /**
120
+ * Fully loaded config result including resolved file path.
121
+ */
122
+ interface LoadedGeneratorConfig {
123
+ configPath: string;
124
+ config: NormalizedAthenaGeneratorConfig;
125
+ }
126
+ type GeneratorArtifactKind = 'model' | 'schema' | 'database' | 'registry';
127
+ /**
128
+ * One generated output file.
129
+ */
130
+ interface GeneratedArtifact {
131
+ kind: GeneratorArtifactKind;
132
+ path: string;
133
+ content: string;
134
+ }
135
+ /**
136
+ * In-memory generator output payload.
137
+ */
138
+ interface GeneratedArtifacts {
139
+ snapshot: IntrospectionSnapshot;
140
+ files: GeneratedArtifact[];
141
+ }
142
+ /**
143
+ * Runtime options for executing the generator pipeline.
144
+ */
145
+ interface RunGeneratorOptions {
146
+ cwd?: string;
147
+ configPath?: string;
148
+ dryRun?: boolean;
149
+ provider?: SchemaIntrospectionProvider;
150
+ }
151
+ /**
152
+ * Generator execution result including files written to disk.
153
+ */
154
+ interface RunGeneratorResult extends GeneratedArtifacts {
155
+ configPath: string;
156
+ writtenFiles: string[];
157
+ }
158
+
159
+ /**
160
+ * End-to-end generator execution: load config, introspect, render, and optionally write files.
161
+ */
162
+ declare function runSchemaGenerator(options?: RunGeneratorOptions): Promise<RunGeneratorResult>;
163
+
164
+ export { type AthenaGeneratorConfig as A, type GeneratedArtifacts as G, type LoadGeneratorConfigOptions as L, type NormalizedAthenaGeneratorConfig as N, type RunGeneratorOptions as R, type LoadedGeneratorConfig as a, type GeneratorProviderConfig as b, type GeneratorExperimentalFlags as c, type GeneratorSchemaSelection as d, type GeneratedArtifact as e, type GeneratorArtifactKind as f, type GeneratorFeatureFlags as g, type GeneratorNamingConfig as h, type GeneratorOutputConfig as i, type GeneratorOutputTargets as j, type NamingStyle as k, type RunGeneratorResult as l, runSchemaGenerator as r };
@@ -0,0 +1,164 @@
1
+ import { a as BackendType, p as IntrospectionSnapshot, o as SchemaIntrospectionProvider } from './types-BnzoaNRC.js';
2
+
3
+ /**
4
+ * Supported case transformations for generated symbols and path token variants.
5
+ */
6
+ type NamingStyle = 'preserve' | 'camel' | 'pascal' | 'snake' | 'kebab';
7
+ /**
8
+ * Naming configuration for generated TypeScript identifiers.
9
+ */
10
+ interface GeneratorNamingConfig {
11
+ modelType: NamingStyle;
12
+ modelConst: NamingStyle;
13
+ schemaConst: NamingStyle;
14
+ databaseConst: NamingStyle;
15
+ registryConst: NamingStyle;
16
+ }
17
+ /**
18
+ * Stable feature flags for generator output behavior.
19
+ */
20
+ interface GeneratorFeatureFlags {
21
+ emitRelations: boolean;
22
+ emitRegistry: boolean;
23
+ }
24
+ /**
25
+ * Experimental toggles for optional/forward-compatible generator behavior.
26
+ */
27
+ interface GeneratorExperimentalFlags {
28
+ /**
29
+ * Legacy compatibility toggle from the initial scaffold.
30
+ * Gateway introspection is now implemented; this flag is retained for additive config compatibility.
31
+ */
32
+ postgresGatewayIntrospection: boolean;
33
+ /**
34
+ * Enables contract placeholders for future Scylla provider work.
35
+ */
36
+ scyllaProviderContracts: boolean;
37
+ }
38
+ /**
39
+ * Path templates for each generated artifact category.
40
+ */
41
+ interface GeneratorOutputTargets {
42
+ model: string;
43
+ schema: string;
44
+ database: string;
45
+ registry: string;
46
+ }
47
+ /**
48
+ * Output configuration including dynamic placeholder aliases.
49
+ */
50
+ interface GeneratorOutputConfig {
51
+ targets: GeneratorOutputTargets;
52
+ placeholderMap: Record<string, string>;
53
+ }
54
+ /**
55
+ * Schemas selected for PostgreSQL introspection. Strings may be comma-separated
56
+ * to support env-driven configs such as `process.env.GENERATOR_SCHEMAS`.
57
+ */
58
+ type GeneratorSchemaSelection = string | readonly string[];
59
+ /**
60
+ * Direct PostgreSQL introspection mode (implemented).
61
+ */
62
+ interface PostgresDirectProviderConfig {
63
+ kind: 'postgres';
64
+ mode: 'direct';
65
+ connectionString: string;
66
+ database?: string;
67
+ schemas?: GeneratorSchemaSelection;
68
+ }
69
+ /**
70
+ * Athena gateway-backed PostgreSQL introspection mode using `/gateway/query`.
71
+ */
72
+ interface PostgresGatewayProviderConfig {
73
+ kind: 'postgres';
74
+ mode: 'gateway';
75
+ gatewayUrl: string;
76
+ apiKey: string;
77
+ database: string;
78
+ schemas?: GeneratorSchemaSelection;
79
+ backend?: BackendType;
80
+ }
81
+ /**
82
+ * Scylla introspection provider contract placeholder (phase-two scaffold).
83
+ */
84
+ interface ScyllaDirectProviderConfig {
85
+ kind: 'scylla';
86
+ mode: 'direct';
87
+ contactPoints: string[];
88
+ keyspace: string;
89
+ datacenter?: string;
90
+ }
91
+ type GeneratorProviderConfig = PostgresDirectProviderConfig | PostgresGatewayProviderConfig | ScyllaDirectProviderConfig;
92
+ /**
93
+ * Root config contract loaded from `athena.config.ts`.
94
+ */
95
+ interface AthenaGeneratorConfig {
96
+ provider: GeneratorProviderConfig;
97
+ output: GeneratorOutputConfig;
98
+ naming?: Partial<GeneratorNamingConfig>;
99
+ features?: Partial<GeneratorFeatureFlags>;
100
+ experimental?: Partial<GeneratorExperimentalFlags>;
101
+ }
102
+ /**
103
+ * Normalized generator config with defaults applied.
104
+ */
105
+ interface NormalizedAthenaGeneratorConfig {
106
+ provider: GeneratorProviderConfig;
107
+ output: GeneratorOutputConfig;
108
+ naming: GeneratorNamingConfig;
109
+ features: GeneratorFeatureFlags;
110
+ experimental: GeneratorExperimentalFlags;
111
+ }
112
+ /**
113
+ * Config loader options for CLI/programmatic usage.
114
+ */
115
+ interface LoadGeneratorConfigOptions {
116
+ cwd?: string;
117
+ configPath?: string;
118
+ }
119
+ /**
120
+ * Fully loaded config result including resolved file path.
121
+ */
122
+ interface LoadedGeneratorConfig {
123
+ configPath: string;
124
+ config: NormalizedAthenaGeneratorConfig;
125
+ }
126
+ type GeneratorArtifactKind = 'model' | 'schema' | 'database' | 'registry';
127
+ /**
128
+ * One generated output file.
129
+ */
130
+ interface GeneratedArtifact {
131
+ kind: GeneratorArtifactKind;
132
+ path: string;
133
+ content: string;
134
+ }
135
+ /**
136
+ * In-memory generator output payload.
137
+ */
138
+ interface GeneratedArtifacts {
139
+ snapshot: IntrospectionSnapshot;
140
+ files: GeneratedArtifact[];
141
+ }
142
+ /**
143
+ * Runtime options for executing the generator pipeline.
144
+ */
145
+ interface RunGeneratorOptions {
146
+ cwd?: string;
147
+ configPath?: string;
148
+ dryRun?: boolean;
149
+ provider?: SchemaIntrospectionProvider;
150
+ }
151
+ /**
152
+ * Generator execution result including files written to disk.
153
+ */
154
+ interface RunGeneratorResult extends GeneratedArtifacts {
155
+ configPath: string;
156
+ writtenFiles: string[];
157
+ }
158
+
159
+ /**
160
+ * End-to-end generator execution: load config, introspect, render, and optionally write files.
161
+ */
162
+ declare function runSchemaGenerator(options?: RunGeneratorOptions): Promise<RunGeneratorResult>;
163
+
164
+ export { type AthenaGeneratorConfig as A, type GeneratedArtifacts as G, type LoadGeneratorConfigOptions as L, type NormalizedAthenaGeneratorConfig as N, type RunGeneratorOptions as R, type LoadedGeneratorConfig as a, type GeneratorProviderConfig as b, type GeneratorExperimentalFlags as c, type GeneratorSchemaSelection as d, type GeneratedArtifact as e, type GeneratorArtifactKind as f, type GeneratorFeatureFlags as g, type GeneratorNamingConfig as h, type GeneratorOutputConfig as i, type GeneratorOutputTargets as j, type NamingStyle as k, type RunGeneratorResult as l, runSchemaGenerator as r };
package/dist/react.cjs CHANGED
@@ -1493,16 +1493,173 @@ function useMutation(options) {
1493
1493
  lastRequest: snapshot.lastRequest
1494
1494
  };
1495
1495
  }
1496
+ function resolveGetSession(authClient) {
1497
+ if ("getSession" in authClient && typeof authClient.getSession === "function") {
1498
+ return authClient.getSession;
1499
+ }
1500
+ if ("auth" in authClient && authClient.auth && typeof authClient.auth.getSession === "function") {
1501
+ return authClient.auth.getSession;
1502
+ }
1503
+ throw new Error("useSession requires an auth-capable client (createClient(...).auth or createAuthClient(...))");
1504
+ }
1505
+ function useSession(authClient, options = {}) {
1506
+ const enabled = options.enabled ?? true;
1507
+ const refetchOnMount = options.refetchOnMount ?? true;
1508
+ const [data, setData] = react.useState(null);
1509
+ const [error, setError] = react.useState(null);
1510
+ const [isPending, setIsPending] = react.useState(enabled);
1511
+ const [isRefetching, setIsRefetching] = react.useState(false);
1512
+ const requestIdRef = react.useRef(0);
1513
+ const mountedRef = react.useRef(true);
1514
+ const dataRef = react.useRef(null);
1515
+ const getSession = resolveGetSession(
1516
+ authClient
1517
+ );
1518
+ react.useEffect(() => {
1519
+ dataRef.current = data;
1520
+ }, [data]);
1521
+ const toFallbackErrorDetails = (code, message, status) => ({
1522
+ code,
1523
+ message,
1524
+ status
1525
+ });
1526
+ const runFetch = react.useCallback(async () => {
1527
+ const requestId = ++requestIdRef.current;
1528
+ const hasData = dataRef.current !== null;
1529
+ if (hasData) {
1530
+ setIsRefetching(true);
1531
+ } else {
1532
+ setIsPending(true);
1533
+ }
1534
+ try {
1535
+ const result = await getSession(options.fetchInput, options.callOptions);
1536
+ if (!mountedRef.current || requestId !== requestIdRef.current) {
1537
+ return null;
1538
+ }
1539
+ if (result.ok) {
1540
+ setData(result.data ?? null);
1541
+ setError(null);
1542
+ return result.data ?? null;
1543
+ }
1544
+ setError(
1545
+ result.errorDetails ?? toFallbackErrorDetails(
1546
+ "UNKNOWN_ERROR",
1547
+ result.error ?? "Failed to fetch session",
1548
+ result.status
1549
+ )
1550
+ );
1551
+ return null;
1552
+ } catch (requestError) {
1553
+ if (!mountedRef.current || requestId !== requestIdRef.current) {
1554
+ return null;
1555
+ }
1556
+ const message = requestError instanceof Error ? requestError.message : "Failed to fetch session";
1557
+ setError(toFallbackErrorDetails("NETWORK_ERROR", message, 0));
1558
+ return null;
1559
+ } finally {
1560
+ if (mountedRef.current && requestId === requestIdRef.current) {
1561
+ setIsPending(false);
1562
+ setIsRefetching(false);
1563
+ }
1564
+ }
1565
+ }, [getSession, options.callOptions, options.fetchInput]);
1566
+ react.useEffect(() => {
1567
+ mountedRef.current = true;
1568
+ if (enabled && refetchOnMount) {
1569
+ void runFetch();
1570
+ } else {
1571
+ setIsPending(false);
1572
+ }
1573
+ return () => {
1574
+ mountedRef.current = false;
1575
+ };
1576
+ }, [enabled, refetchOnMount, runFetch]);
1577
+ const refetch = react.useCallback(async () => {
1578
+ return await runFetch();
1579
+ }, [runFetch]);
1580
+ return {
1581
+ data,
1582
+ error,
1583
+ isPending,
1584
+ isRefetching,
1585
+ refetch
1586
+ };
1587
+ }
1588
+
1589
+ // src/schema/model-form.ts
1590
+ function resolveNullishValue(mode) {
1591
+ if (mode === "undefined") return void 0;
1592
+ if (mode === "null") return null;
1593
+ return "";
1594
+ }
1595
+ function isRecord3(value) {
1596
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1597
+ }
1598
+ function isNullableColumn(model, key) {
1599
+ const nullable = model.meta.nullable;
1600
+ return nullable?.[key] === true;
1601
+ }
1602
+ function toModelFormDefaults(model, values, options) {
1603
+ const source = values;
1604
+ if (!isRecord3(source)) {
1605
+ return {};
1606
+ }
1607
+ const mode = options?.nullishMode ?? "empty-string";
1608
+ const nullishValue = resolveNullishValue(mode);
1609
+ const result = {};
1610
+ for (const [key, value] of Object.entries(source)) {
1611
+ if (value === null && isNullableColumn(model, key)) {
1612
+ result[key] = nullishValue;
1613
+ continue;
1614
+ }
1615
+ result[key] = value;
1616
+ }
1617
+ return result;
1618
+ }
1619
+ function toModelPayload(model, formValues, options) {
1620
+ const emptyStringAsNull = options?.emptyStringAsNull ?? true;
1621
+ const stripUndefined = options?.stripUndefined ?? true;
1622
+ const result = {};
1623
+ for (const [key, rawValue] of Object.entries(formValues)) {
1624
+ if (rawValue === void 0 && stripUndefined) {
1625
+ continue;
1626
+ }
1627
+ if (emptyStringAsNull && rawValue === "" && isNullableColumn(model, key)) {
1628
+ result[key] = null;
1629
+ continue;
1630
+ }
1631
+ result[key] = rawValue;
1632
+ }
1633
+ return result;
1634
+ }
1635
+ function createModelFormAdapter(model) {
1636
+ return {
1637
+ model,
1638
+ toDefaults(values, options) {
1639
+ return toModelFormDefaults(model, values, options);
1640
+ },
1641
+ toInsert(values, options) {
1642
+ return toModelPayload(model, values, options);
1643
+ },
1644
+ toUpdate(values, options) {
1645
+ return toModelPayload(model, values, options);
1646
+ }
1647
+ };
1648
+ }
1496
1649
 
1497
1650
  exports.AthenaGatewayError = AthenaGatewayError;
1498
1651
  exports.AthenaQueryClient = AthenaQueryClient;
1499
1652
  exports.AthenaQueryClientProvider = AthenaQueryClientProvider;
1500
1653
  exports.attachStateAdapter = attachStateAdapter;
1501
1654
  exports.createAthenaQueryClient = createAthenaQueryClient;
1655
+ exports.createModelFormAdapter = createModelFormAdapter;
1502
1656
  exports.isAthenaGatewayError = isAthenaGatewayError;
1657
+ exports.toModelFormDefaults = toModelFormDefaults;
1658
+ exports.toModelPayload = toModelPayload;
1503
1659
  exports.useAthenaGateway = useAthenaGateway;
1504
1660
  exports.useAthenaQueryClient = useAthenaQueryClient;
1505
1661
  exports.useMutation = useMutation;
1506
1662
  exports.useQuery = useQuery;
1663
+ exports.useSession = useSession;
1507
1664
  //# sourceMappingURL=react.cjs.map
1508
1665
  //# sourceMappingURL=react.cjs.map