@xylex-group/athena 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/billing.cjs +1 -1
- package/dist/billing.cjs.map +1 -1
- package/dist/billing.js +1 -1
- package/dist/billing.js.map +1 -1
- package/dist/browser.cjs +322 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +5 -5
- package/dist/browser.d.ts +5 -5
- package/dist/browser.js +301 -2
- package/dist/browser.js.map +1 -1
- package/dist/cli/index.cjs +5381 -3772
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +17 -10
- package/dist/cli/index.d.ts +17 -10
- package/dist/cli/index.js +5385 -3776
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +1723 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -6
- package/dist/index.d.ts +28 -6
- package/dist/index.js +1695 -28
- package/dist/index.js.map +1 -1
- package/dist/model-form-BbdzJ9Uh.d.ts +259 -0
- package/dist/model-form-BhWWsA-7.d.cts +259 -0
- package/dist/{module-CkUM6v58.d.ts → module-DKkJKOuJ.d.ts} +2 -2
- package/dist/{module-CB25egcO.d.cts → module-xFd7_Igv.d.cts} +2 -2
- package/dist/next/client.cjs +1 -1
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.js +1 -1
- package/dist/next/client.js.map +1 -1
- package/dist/next/server.cjs +1 -1
- package/dist/next/server.cjs.map +1 -1
- package/dist/next/server.js +1 -1
- package/dist/next/server.js.map +1 -1
- package/dist/pipeline-DuKzYGia.d.cts +93 -0
- package/dist/pipeline-wer2G9xW.d.ts +93 -0
- package/dist/react.cjs +400 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +67 -2
- package/dist/react.d.ts +67 -2
- package/dist/react.js +400 -4
- package/dist/react.js.map +1 -1
- package/dist/{types-BBm-kEBL.d.cts → types-1ztXDgPa.d.cts} +62 -2
- package/dist/{types-BaAMXCqK.d.ts → types-CccOiXPo.d.ts} +62 -2
- package/package.json +1 -1
- package/dist/model-form-Dh0sisdL.d.ts +0 -97
- package/dist/model-form-oOAJUVd4.d.cts +0 -97
- package/dist/pipeline-B8aN2EHe.d.ts +0 -8
- package/dist/pipeline-D4W-Cc-A.d.cts +0 -8
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { b as GeneratorProviderConfig, a as LoadedGeneratorConfig, R as RunGeneratorOptions, d as RunGeneratorResult } from './types-1ztXDgPa.cjs';
|
|
2
|
+
|
|
3
|
+
type GeneratorConfigFileAction = 'created' | 'updated' | 'unchanged' | 'skipped';
|
|
4
|
+
type GeneratorConfigProviderMode = 'direct' | 'gateway' | 'auto';
|
|
5
|
+
interface EnsureGeneratorConfigFileOptions {
|
|
6
|
+
cwd?: string;
|
|
7
|
+
/** Explicit path relative to cwd or absolute. Defaults to discovered path or `athena.config.ts`. */
|
|
8
|
+
configPath?: string;
|
|
9
|
+
/** Provider mode preference when creating a new file. */
|
|
10
|
+
mode?: GeneratorConfigProviderMode;
|
|
11
|
+
/**
|
|
12
|
+
* Discover live schemas and auto-fill `provider.schemas`.
|
|
13
|
+
* Defaults to true.
|
|
14
|
+
*/
|
|
15
|
+
discoverSchemas?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* When false, never write to disk (report would-be action only).
|
|
18
|
+
* Defaults to false.
|
|
19
|
+
*/
|
|
20
|
+
dryRun?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* When true, rewrite the full modern template even if a file already exists.
|
|
23
|
+
* Defaults to false (intelligent surgical update only).
|
|
24
|
+
*/
|
|
25
|
+
force?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Pre-resolved provider used for schema discovery (avoids re-normalizing).
|
|
28
|
+
*/
|
|
29
|
+
provider?: GeneratorProviderConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Optional pre-loaded config (skips a second disk load).
|
|
32
|
+
*/
|
|
33
|
+
loaded?: LoadedGeneratorConfig;
|
|
34
|
+
/**
|
|
35
|
+
* Explicit schemas to write when discovery is disabled or fails.
|
|
36
|
+
*/
|
|
37
|
+
schemas?: readonly string[];
|
|
38
|
+
}
|
|
39
|
+
interface EnsureGeneratorConfigFileResult {
|
|
40
|
+
action: GeneratorConfigFileAction;
|
|
41
|
+
path: string;
|
|
42
|
+
absolutePath: string;
|
|
43
|
+
content?: string;
|
|
44
|
+
schemas: string[];
|
|
45
|
+
changes: string[];
|
|
46
|
+
mode: 'direct' | 'gateway';
|
|
47
|
+
reason?: string;
|
|
48
|
+
}
|
|
49
|
+
type DetectedMode = 'direct' | 'gateway';
|
|
50
|
+
/**
|
|
51
|
+
* Picks a provider mode from env when the caller did not force one.
|
|
52
|
+
* Prefers direct when a connection string is present; otherwise gateway.
|
|
53
|
+
*/
|
|
54
|
+
declare function detectGeneratorProviderMode(preferred?: GeneratorConfigProviderMode): DetectedMode;
|
|
55
|
+
/**
|
|
56
|
+
* Renders a modern, typed `athena.config.ts` using `defineGeneratorConfig` + `generatorEnv`.
|
|
57
|
+
* Secrets stay env-backed so gateway and direct modes both work without hardcoding keys.
|
|
58
|
+
*/
|
|
59
|
+
declare function renderGeneratorConfigFile(options: {
|
|
60
|
+
mode: DetectedMode;
|
|
61
|
+
schemas?: readonly string[];
|
|
62
|
+
}): string;
|
|
63
|
+
/**
|
|
64
|
+
* Updates only the `schemas:` value inside an existing TypeScript config source.
|
|
65
|
+
* Supports:
|
|
66
|
+
* - `schemas: ["public", "athena"]`
|
|
67
|
+
* - `schemas: generatorEnv.list("...", { default: ["public"] })`
|
|
68
|
+
*
|
|
69
|
+
* Returns undefined when the file cannot be updated surgically (caller may full-render).
|
|
70
|
+
*/
|
|
71
|
+
declare function patchSchemasInConfigSource(source: string, schemas: readonly string[]): string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Creates or intelligently updates `athena.config.ts`.
|
|
74
|
+
*
|
|
75
|
+
* Intelligence rules:
|
|
76
|
+
* - missing file → write modern direct/gateway template with env-backed secrets
|
|
77
|
+
* - existing file + force → full rewrite
|
|
78
|
+
* - existing file → only patch `provider.schemas` when auto-fill finds new values
|
|
79
|
+
* - skip write when content/schemas already match (no churn, safe for typecheck CI)
|
|
80
|
+
* - never removes user-listed schemas that discovery did not return
|
|
81
|
+
* - gateway mode uses the same template surface as direct (generatorEnv for url/key)
|
|
82
|
+
*/
|
|
83
|
+
declare function ensureGeneratorConfigFile(options?: EnsureGeneratorConfigFileOptions): Promise<EnsureGeneratorConfigFileResult>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* End-to-end generator execution: load config, introspect, render, and optionally write files.
|
|
87
|
+
*
|
|
88
|
+
* When `writeConfig` is enabled (default), also ensures `athena.config.ts` exists and
|
|
89
|
+
* auto-fills discovered schemas without clobbering custom config fields.
|
|
90
|
+
*/
|
|
91
|
+
declare function runSchemaGenerator(options?: RunGeneratorOptions): Promise<RunGeneratorResult>;
|
|
92
|
+
|
|
93
|
+
export { type EnsureGeneratorConfigFileOptions as E, type GeneratorConfigFileAction as G, type EnsureGeneratorConfigFileResult as a, type GeneratorConfigProviderMode as b, renderGeneratorConfigFile as c, detectGeneratorProviderMode as d, ensureGeneratorConfigFile as e, patchSchemasInConfigSource as p, runSchemaGenerator as r };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { b as GeneratorProviderConfig, a as LoadedGeneratorConfig, R as RunGeneratorOptions, d as RunGeneratorResult } from './types-CccOiXPo.js';
|
|
2
|
+
|
|
3
|
+
type GeneratorConfigFileAction = 'created' | 'updated' | 'unchanged' | 'skipped';
|
|
4
|
+
type GeneratorConfigProviderMode = 'direct' | 'gateway' | 'auto';
|
|
5
|
+
interface EnsureGeneratorConfigFileOptions {
|
|
6
|
+
cwd?: string;
|
|
7
|
+
/** Explicit path relative to cwd or absolute. Defaults to discovered path or `athena.config.ts`. */
|
|
8
|
+
configPath?: string;
|
|
9
|
+
/** Provider mode preference when creating a new file. */
|
|
10
|
+
mode?: GeneratorConfigProviderMode;
|
|
11
|
+
/**
|
|
12
|
+
* Discover live schemas and auto-fill `provider.schemas`.
|
|
13
|
+
* Defaults to true.
|
|
14
|
+
*/
|
|
15
|
+
discoverSchemas?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* When false, never write to disk (report would-be action only).
|
|
18
|
+
* Defaults to false.
|
|
19
|
+
*/
|
|
20
|
+
dryRun?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* When true, rewrite the full modern template even if a file already exists.
|
|
23
|
+
* Defaults to false (intelligent surgical update only).
|
|
24
|
+
*/
|
|
25
|
+
force?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Pre-resolved provider used for schema discovery (avoids re-normalizing).
|
|
28
|
+
*/
|
|
29
|
+
provider?: GeneratorProviderConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Optional pre-loaded config (skips a second disk load).
|
|
32
|
+
*/
|
|
33
|
+
loaded?: LoadedGeneratorConfig;
|
|
34
|
+
/**
|
|
35
|
+
* Explicit schemas to write when discovery is disabled or fails.
|
|
36
|
+
*/
|
|
37
|
+
schemas?: readonly string[];
|
|
38
|
+
}
|
|
39
|
+
interface EnsureGeneratorConfigFileResult {
|
|
40
|
+
action: GeneratorConfigFileAction;
|
|
41
|
+
path: string;
|
|
42
|
+
absolutePath: string;
|
|
43
|
+
content?: string;
|
|
44
|
+
schemas: string[];
|
|
45
|
+
changes: string[];
|
|
46
|
+
mode: 'direct' | 'gateway';
|
|
47
|
+
reason?: string;
|
|
48
|
+
}
|
|
49
|
+
type DetectedMode = 'direct' | 'gateway';
|
|
50
|
+
/**
|
|
51
|
+
* Picks a provider mode from env when the caller did not force one.
|
|
52
|
+
* Prefers direct when a connection string is present; otherwise gateway.
|
|
53
|
+
*/
|
|
54
|
+
declare function detectGeneratorProviderMode(preferred?: GeneratorConfigProviderMode): DetectedMode;
|
|
55
|
+
/**
|
|
56
|
+
* Renders a modern, typed `athena.config.ts` using `defineGeneratorConfig` + `generatorEnv`.
|
|
57
|
+
* Secrets stay env-backed so gateway and direct modes both work without hardcoding keys.
|
|
58
|
+
*/
|
|
59
|
+
declare function renderGeneratorConfigFile(options: {
|
|
60
|
+
mode: DetectedMode;
|
|
61
|
+
schemas?: readonly string[];
|
|
62
|
+
}): string;
|
|
63
|
+
/**
|
|
64
|
+
* Updates only the `schemas:` value inside an existing TypeScript config source.
|
|
65
|
+
* Supports:
|
|
66
|
+
* - `schemas: ["public", "athena"]`
|
|
67
|
+
* - `schemas: generatorEnv.list("...", { default: ["public"] })`
|
|
68
|
+
*
|
|
69
|
+
* Returns undefined when the file cannot be updated surgically (caller may full-render).
|
|
70
|
+
*/
|
|
71
|
+
declare function patchSchemasInConfigSource(source: string, schemas: readonly string[]): string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Creates or intelligently updates `athena.config.ts`.
|
|
74
|
+
*
|
|
75
|
+
* Intelligence rules:
|
|
76
|
+
* - missing file → write modern direct/gateway template with env-backed secrets
|
|
77
|
+
* - existing file + force → full rewrite
|
|
78
|
+
* - existing file → only patch `provider.schemas` when auto-fill finds new values
|
|
79
|
+
* - skip write when content/schemas already match (no churn, safe for typecheck CI)
|
|
80
|
+
* - never removes user-listed schemas that discovery did not return
|
|
81
|
+
* - gateway mode uses the same template surface as direct (generatorEnv for url/key)
|
|
82
|
+
*/
|
|
83
|
+
declare function ensureGeneratorConfigFile(options?: EnsureGeneratorConfigFileOptions): Promise<EnsureGeneratorConfigFileResult>;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* End-to-end generator execution: load config, introspect, render, and optionally write files.
|
|
87
|
+
*
|
|
88
|
+
* When `writeConfig` is enabled (default), also ensures `athena.config.ts` exists and
|
|
89
|
+
* auto-fills discovered schemas without clobbering custom config fields.
|
|
90
|
+
*/
|
|
91
|
+
declare function runSchemaGenerator(options?: RunGeneratorOptions): Promise<RunGeneratorResult>;
|
|
92
|
+
|
|
93
|
+
export { type EnsureGeneratorConfigFileOptions as E, type GeneratorConfigFileAction as G, type EnsureGeneratorConfigFileResult as a, type GeneratorConfigProviderMode as b, renderGeneratorConfigFile as c, detectGeneratorProviderMode as d, ensureGeneratorConfigFile as e, patchSchemasInConfigSource as p, runSchemaGenerator as r };
|
package/dist/react.cjs
CHANGED
|
@@ -413,7 +413,7 @@ function buildAthenaRequestHeaders(input) {
|
|
|
413
413
|
|
|
414
414
|
// package.json
|
|
415
415
|
var package_default = {
|
|
416
|
-
version: "3.0
|
|
416
|
+
version: "3.1.0"
|
|
417
417
|
};
|
|
418
418
|
|
|
419
419
|
// src/sdk-version.ts
|
|
@@ -1997,6 +1997,402 @@ function useMutation(options) {
|
|
|
1997
1997
|
lastRequest: snapshot.lastRequest
|
|
1998
1998
|
};
|
|
1999
1999
|
}
|
|
2000
|
+
|
|
2001
|
+
// src/query-debug-ast.ts
|
|
2002
|
+
var ATHENA_DEBUG_AST_KEY = "__athenaDebugAst";
|
|
2003
|
+
function getAthenaDebugAst(value) {
|
|
2004
|
+
if (!value || typeof value !== "object" && typeof value !== "function") {
|
|
2005
|
+
return null;
|
|
2006
|
+
}
|
|
2007
|
+
return value[ATHENA_DEBUG_AST_KEY] ?? null;
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
// src/query/read-query.ts
|
|
2011
|
+
function normalizeAthenaReadQueryOrderBy(orderBy) {
|
|
2012
|
+
if (!orderBy) {
|
|
2013
|
+
return [];
|
|
2014
|
+
}
|
|
2015
|
+
const list = Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
2016
|
+
return list.filter(
|
|
2017
|
+
(entry) => entry && typeof entry.column === "string" && entry.column.trim().length > 0
|
|
2018
|
+
);
|
|
2019
|
+
}
|
|
2020
|
+
function isRecord3(value) {
|
|
2021
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2022
|
+
}
|
|
2023
|
+
function flattenAthenaRowValue(row, column) {
|
|
2024
|
+
if (!column.relation) {
|
|
2025
|
+
return row[column.column];
|
|
2026
|
+
}
|
|
2027
|
+
const relationValue = row[column.relation.name];
|
|
2028
|
+
if (Array.isArray(relationValue)) {
|
|
2029
|
+
return relationValue.map((entry) => isRecord3(entry) ? entry[column.column] : void 0).filter((entry) => entry !== void 0);
|
|
2030
|
+
}
|
|
2031
|
+
if (isRecord3(relationValue)) {
|
|
2032
|
+
return relationValue[column.column];
|
|
2033
|
+
}
|
|
2034
|
+
return void 0;
|
|
2035
|
+
}
|
|
2036
|
+
function resolveFlatRowKey(row, index, preferredKey) {
|
|
2037
|
+
const preferredValue = preferredKey && preferredKey in row ? row[preferredKey] : void 0;
|
|
2038
|
+
if (preferredValue !== void 0 && preferredValue !== null && `${preferredValue}`.trim().length > 0) {
|
|
2039
|
+
return String(preferredValue);
|
|
2040
|
+
}
|
|
2041
|
+
for (const [key, value] of Object.entries(row)) {
|
|
2042
|
+
if (key === "__rowKey") {
|
|
2043
|
+
continue;
|
|
2044
|
+
}
|
|
2045
|
+
if (value === void 0 || value === null) {
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2048
|
+
if (Array.isArray(value)) {
|
|
2049
|
+
if (value.length > 0) {
|
|
2050
|
+
return `${key}-${value.join("-")}`;
|
|
2051
|
+
}
|
|
2052
|
+
continue;
|
|
2053
|
+
}
|
|
2054
|
+
const nextValue = String(value).trim();
|
|
2055
|
+
if (nextValue.length > 0) {
|
|
2056
|
+
return nextValue;
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
return `row-${index + 1}`;
|
|
2060
|
+
}
|
|
2061
|
+
function flattenAthenaReadQueryRows(rows, columns, preferredKey) {
|
|
2062
|
+
return rows.map((entry, index) => {
|
|
2063
|
+
const sourceRow = isRecord3(entry) ? entry : {};
|
|
2064
|
+
const flatRow = columns.reduce(
|
|
2065
|
+
(currentRow, column) => {
|
|
2066
|
+
currentRow[column.key] = flattenAthenaRowValue(sourceRow, column);
|
|
2067
|
+
return currentRow;
|
|
2068
|
+
},
|
|
2069
|
+
{ __rowKey: "" }
|
|
2070
|
+
);
|
|
2071
|
+
flatRow.__rowKey = resolveFlatRowKey(flatRow, index, preferredKey);
|
|
2072
|
+
return flatRow;
|
|
2073
|
+
});
|
|
2074
|
+
}
|
|
2075
|
+
function buildAthenaReadQuerySelectString(columns) {
|
|
2076
|
+
const baseColumns = columns.filter((column) => !column.relation).map((column) => column.column);
|
|
2077
|
+
const relationGroups = /* @__PURE__ */ new Map();
|
|
2078
|
+
for (const column of columns) {
|
|
2079
|
+
if (!column.relation) {
|
|
2080
|
+
continue;
|
|
2081
|
+
}
|
|
2082
|
+
const groupKey = [
|
|
2083
|
+
column.relation.name,
|
|
2084
|
+
column.relation.schema ?? "",
|
|
2085
|
+
column.relation.table
|
|
2086
|
+
].join(":");
|
|
2087
|
+
const existingGroup = relationGroups.get(groupKey);
|
|
2088
|
+
if (existingGroup) {
|
|
2089
|
+
if (!existingGroup.columns.includes(column.column)) {
|
|
2090
|
+
existingGroup.columns.push(column.column);
|
|
2091
|
+
}
|
|
2092
|
+
continue;
|
|
2093
|
+
}
|
|
2094
|
+
relationGroups.set(groupKey, {
|
|
2095
|
+
columns: [column.column],
|
|
2096
|
+
relation: column.relation
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
const relationColumns = [...relationGroups.values()].map(
|
|
2100
|
+
({ columns: relationColumns2, relation }) => {
|
|
2101
|
+
const relationTarget = relation.schema ? `${relation.schema}.${relation.table}` : relation.table;
|
|
2102
|
+
return `${relation.name}:${relationTarget}(${relationColumns2.join(",")})`;
|
|
2103
|
+
}
|
|
2104
|
+
);
|
|
2105
|
+
return [...baseColumns, ...relationColumns].join(",");
|
|
2106
|
+
}
|
|
2107
|
+
function buildAthenaReadQueryFindManySelect(columns) {
|
|
2108
|
+
const select = {};
|
|
2109
|
+
for (const column of columns) {
|
|
2110
|
+
if (!column.relation) {
|
|
2111
|
+
select[column.column] = true;
|
|
2112
|
+
continue;
|
|
2113
|
+
}
|
|
2114
|
+
const existingRelation = select[column.relation.name];
|
|
2115
|
+
if (existingRelation && existingRelation !== true && isRecord3(existingRelation.select)) {
|
|
2116
|
+
existingRelation.select[column.column] = true;
|
|
2117
|
+
continue;
|
|
2118
|
+
}
|
|
2119
|
+
select[column.relation.name] = {
|
|
2120
|
+
...column.relation.schema ? { schema: column.relation.schema } : {},
|
|
2121
|
+
select: {
|
|
2122
|
+
[column.column]: true
|
|
2123
|
+
}
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
return select;
|
|
2127
|
+
}
|
|
2128
|
+
function buildAthenaReadQueryFindManyWhere(filters) {
|
|
2129
|
+
if (!filters?.length) {
|
|
2130
|
+
return;
|
|
2131
|
+
}
|
|
2132
|
+
return filters.reduce(
|
|
2133
|
+
(where, filter) => {
|
|
2134
|
+
const operator = filter.operator ?? "eq";
|
|
2135
|
+
where[filter.column] = operator === "eq" ? filter.value : { [operator]: filter.value };
|
|
2136
|
+
return where;
|
|
2137
|
+
},
|
|
2138
|
+
{}
|
|
2139
|
+
);
|
|
2140
|
+
}
|
|
2141
|
+
function buildAthenaReadQueryFindManyOrderBy(orderBy) {
|
|
2142
|
+
const normalized = normalizeAthenaReadQueryOrderBy(orderBy);
|
|
2143
|
+
if (normalized.length === 0) {
|
|
2144
|
+
return;
|
|
2145
|
+
}
|
|
2146
|
+
if (normalized.length === 1) {
|
|
2147
|
+
const primary = normalized[0];
|
|
2148
|
+
if (!primary) {
|
|
2149
|
+
return;
|
|
2150
|
+
}
|
|
2151
|
+
return {
|
|
2152
|
+
ascending: primary.direction !== "desc",
|
|
2153
|
+
column: primary.column
|
|
2154
|
+
};
|
|
2155
|
+
}
|
|
2156
|
+
return Object.fromEntries(
|
|
2157
|
+
normalized.map((entry) => [
|
|
2158
|
+
entry.column,
|
|
2159
|
+
entry.direction === "desc" ? "desc" : "asc"
|
|
2160
|
+
])
|
|
2161
|
+
);
|
|
2162
|
+
}
|
|
2163
|
+
function applyAthenaReadQueryFilters(queryBuilder, filters) {
|
|
2164
|
+
if (!filters?.length) {
|
|
2165
|
+
return queryBuilder;
|
|
2166
|
+
}
|
|
2167
|
+
return filters.reduce((currentBuilder, filter) => {
|
|
2168
|
+
const operator = filter.operator ?? "eq";
|
|
2169
|
+
const builderMethod = currentBuilder[operator];
|
|
2170
|
+
if (typeof builderMethod !== "function") {
|
|
2171
|
+
return currentBuilder;
|
|
2172
|
+
}
|
|
2173
|
+
return builderMethod.call(currentBuilder, filter.column, filter.value);
|
|
2174
|
+
}, queryBuilder);
|
|
2175
|
+
}
|
|
2176
|
+
function applyAthenaReadQuerySelectOrder(queryBuilder, orderBy) {
|
|
2177
|
+
const normalized = normalizeAthenaReadQueryOrderBy(orderBy);
|
|
2178
|
+
if (normalized.length === 0) {
|
|
2179
|
+
return queryBuilder;
|
|
2180
|
+
}
|
|
2181
|
+
return normalized.reduce(
|
|
2182
|
+
(builder, entry) => builder.order(entry.column, {
|
|
2183
|
+
ascending: entry.direction !== "desc"
|
|
2184
|
+
}),
|
|
2185
|
+
queryBuilder
|
|
2186
|
+
);
|
|
2187
|
+
}
|
|
2188
|
+
function applyAthenaReadQuerySelectLimit(queryBuilder, limit) {
|
|
2189
|
+
if (!limit || limit < 1) {
|
|
2190
|
+
return queryBuilder;
|
|
2191
|
+
}
|
|
2192
|
+
return queryBuilder.limit(limit);
|
|
2193
|
+
}
|
|
2194
|
+
function clampAthenaReadQueryTotalItems(totalItems, limit) {
|
|
2195
|
+
if (!limit || limit < 1) {
|
|
2196
|
+
return totalItems;
|
|
2197
|
+
}
|
|
2198
|
+
return Math.min(totalItems, limit);
|
|
2199
|
+
}
|
|
2200
|
+
function resolveCountValue(...candidates) {
|
|
2201
|
+
for (const candidate of candidates) {
|
|
2202
|
+
if (typeof candidate === "number" && Number.isFinite(candidate)) {
|
|
2203
|
+
return Math.max(0, Math.trunc(candidate));
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
return 0;
|
|
2207
|
+
}
|
|
2208
|
+
function resolveTotalItemsFromPage({
|
|
2209
|
+
countCandidates,
|
|
2210
|
+
limit,
|
|
2211
|
+
page,
|
|
2212
|
+
pageSize,
|
|
2213
|
+
rowCount
|
|
2214
|
+
}) {
|
|
2215
|
+
const exactCount = resolveCountValue(...countCandidates);
|
|
2216
|
+
if (exactCount > 0) {
|
|
2217
|
+
return clampAthenaReadQueryTotalItems(exactCount, limit);
|
|
2218
|
+
}
|
|
2219
|
+
if (rowCount > 0) {
|
|
2220
|
+
const base = (page - 1) * pageSize + rowCount;
|
|
2221
|
+
const synthetic = rowCount >= pageSize ? base + 1 : base;
|
|
2222
|
+
return clampAthenaReadQueryTotalItems(synthetic, limit);
|
|
2223
|
+
}
|
|
2224
|
+
return clampAthenaReadQueryTotalItems(exactCount, limit);
|
|
2225
|
+
}
|
|
2226
|
+
async function executeAthenaReadQuery({
|
|
2227
|
+
client,
|
|
2228
|
+
page,
|
|
2229
|
+
pageSize,
|
|
2230
|
+
query
|
|
2231
|
+
}) {
|
|
2232
|
+
const db = client.db;
|
|
2233
|
+
const baseBuilder = db.from(query.table, {
|
|
2234
|
+
schema: query.schema
|
|
2235
|
+
});
|
|
2236
|
+
const countBuilder = applyAthenaReadQueryFilters(
|
|
2237
|
+
db.from(query.table, { schema: query.schema }),
|
|
2238
|
+
query.filters
|
|
2239
|
+
);
|
|
2240
|
+
const countResult = await countBuilder.select(query.countColumn, {
|
|
2241
|
+
count: "exact",
|
|
2242
|
+
head: true
|
|
2243
|
+
});
|
|
2244
|
+
if ((query.mode ?? "findMany") === "select") {
|
|
2245
|
+
const selectBuilder = applyAthenaReadQuerySelectLimit(
|
|
2246
|
+
applyAthenaReadQuerySelectOrder(
|
|
2247
|
+
applyAthenaReadQueryFilters(baseBuilder, query.filters),
|
|
2248
|
+
query.orderBy
|
|
2249
|
+
),
|
|
2250
|
+
query.limit
|
|
2251
|
+
);
|
|
2252
|
+
const result2 = await selectBuilder.currentPage(page).pageSize(pageSize).select(buildAthenaReadQuerySelectString(query.columns), {
|
|
2253
|
+
count: "exact"
|
|
2254
|
+
});
|
|
2255
|
+
const rows2 = flattenAthenaReadQueryRows(
|
|
2256
|
+
Array.isArray(result2.data) ? result2.data : [],
|
|
2257
|
+
query.columns,
|
|
2258
|
+
query.rowKey
|
|
2259
|
+
);
|
|
2260
|
+
return {
|
|
2261
|
+
debugAst: getAthenaDebugAst(result2) ?? void 0,
|
|
2262
|
+
rows: rows2,
|
|
2263
|
+
totalItems: resolveTotalItemsFromPage({
|
|
2264
|
+
countCandidates: [countResult.count, result2.count],
|
|
2265
|
+
limit: query.limit,
|
|
2266
|
+
page,
|
|
2267
|
+
pageSize,
|
|
2268
|
+
rowCount: rows2.length
|
|
2269
|
+
})
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
const findManyOrderBy = buildAthenaReadQueryFindManyOrderBy(query.orderBy);
|
|
2273
|
+
const findManyOptions = {
|
|
2274
|
+
...query.limit ? { limit: query.limit } : {},
|
|
2275
|
+
...findManyOrderBy ? { orderBy: findManyOrderBy } : {},
|
|
2276
|
+
select: buildAthenaReadQueryFindManySelect(query.columns),
|
|
2277
|
+
...query.filters?.length ? { where: buildAthenaReadQueryFindManyWhere(query.filters) } : {}
|
|
2278
|
+
};
|
|
2279
|
+
const result = await baseBuilder.currentPage(page).pageSize(pageSize).findMany(findManyOptions);
|
|
2280
|
+
const rows = flattenAthenaReadQueryRows(
|
|
2281
|
+
Array.isArray(result.data) ? result.data : [],
|
|
2282
|
+
query.columns,
|
|
2283
|
+
query.rowKey
|
|
2284
|
+
);
|
|
2285
|
+
return {
|
|
2286
|
+
debugAst: getAthenaDebugAst(result) ?? void 0,
|
|
2287
|
+
rows,
|
|
2288
|
+
totalItems: resolveTotalItemsFromPage({
|
|
2289
|
+
countCandidates: [countResult.count, result.count],
|
|
2290
|
+
limit: query.limit,
|
|
2291
|
+
page,
|
|
2292
|
+
pageSize,
|
|
2293
|
+
rowCount: rows.length
|
|
2294
|
+
})
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2298
|
+
// src/react/use-athena-read-query.ts
|
|
2299
|
+
var DEFAULT_PAGE = 1;
|
|
2300
|
+
var DEFAULT_PAGE_SIZE = 10;
|
|
2301
|
+
function isReadQueryRunnable(query) {
|
|
2302
|
+
return query.table.trim().length > 0 && query.columns.length > 0 && query.countColumn.trim().length > 0;
|
|
2303
|
+
}
|
|
2304
|
+
function useAthenaReadQuery({
|
|
2305
|
+
client,
|
|
2306
|
+
query,
|
|
2307
|
+
page = DEFAULT_PAGE,
|
|
2308
|
+
pageSize = DEFAULT_PAGE_SIZE,
|
|
2309
|
+
enabled = true,
|
|
2310
|
+
queryKey,
|
|
2311
|
+
queryKeyPrefix,
|
|
2312
|
+
refetchOnMount,
|
|
2313
|
+
refetchOnWindowFocus,
|
|
2314
|
+
refetchOnReconnect,
|
|
2315
|
+
retry
|
|
2316
|
+
}) {
|
|
2317
|
+
const resolvedPage = page > 0 ? Math.trunc(page) : DEFAULT_PAGE;
|
|
2318
|
+
const resolvedPageSize = pageSize > 0 ? Math.trunc(pageSize) : DEFAULT_PAGE_SIZE;
|
|
2319
|
+
const queryEnabled = enabled && !!client && isReadQueryRunnable(query);
|
|
2320
|
+
const defaultQueryKey = React.useMemo(
|
|
2321
|
+
() => [
|
|
2322
|
+
"athena",
|
|
2323
|
+
"read-query",
|
|
2324
|
+
query.mode ?? "findMany",
|
|
2325
|
+
query.table,
|
|
2326
|
+
query.schema,
|
|
2327
|
+
query.columns,
|
|
2328
|
+
query.filters,
|
|
2329
|
+
query.limit,
|
|
2330
|
+
query.orderBy,
|
|
2331
|
+
query.rowKey,
|
|
2332
|
+
query.countColumn,
|
|
2333
|
+
resolvedPage,
|
|
2334
|
+
resolvedPageSize
|
|
2335
|
+
],
|
|
2336
|
+
[
|
|
2337
|
+
query.columns,
|
|
2338
|
+
query.countColumn,
|
|
2339
|
+
query.filters,
|
|
2340
|
+
query.limit,
|
|
2341
|
+
query.mode,
|
|
2342
|
+
query.orderBy,
|
|
2343
|
+
query.rowKey,
|
|
2344
|
+
query.schema,
|
|
2345
|
+
query.table,
|
|
2346
|
+
resolvedPage,
|
|
2347
|
+
resolvedPageSize
|
|
2348
|
+
]
|
|
2349
|
+
);
|
|
2350
|
+
const resolvedQueryKey = React.useMemo(() => {
|
|
2351
|
+
if (queryKey !== void 0) {
|
|
2352
|
+
return queryKey;
|
|
2353
|
+
}
|
|
2354
|
+
if (queryKeyPrefix !== void 0) {
|
|
2355
|
+
const prefix = Array.isArray(queryKeyPrefix) ? queryKeyPrefix : [queryKeyPrefix];
|
|
2356
|
+
return [...prefix, ...defaultQueryKey];
|
|
2357
|
+
}
|
|
2358
|
+
return defaultQueryKey;
|
|
2359
|
+
}, [defaultQueryKey, queryKey, queryKeyPrefix]);
|
|
2360
|
+
const result = useQuery({
|
|
2361
|
+
enabled: queryEnabled,
|
|
2362
|
+
queryKey: resolvedQueryKey,
|
|
2363
|
+
queryFn: async () => {
|
|
2364
|
+
if (!client) {
|
|
2365
|
+
throw new Error("Athena client is required to run the read query.");
|
|
2366
|
+
}
|
|
2367
|
+
return executeAthenaReadQuery({
|
|
2368
|
+
client,
|
|
2369
|
+
page: resolvedPage,
|
|
2370
|
+
pageSize: resolvedPageSize,
|
|
2371
|
+
query
|
|
2372
|
+
});
|
|
2373
|
+
},
|
|
2374
|
+
refetchOnMount,
|
|
2375
|
+
refetchOnWindowFocus,
|
|
2376
|
+
refetchOnReconnect,
|
|
2377
|
+
retry
|
|
2378
|
+
});
|
|
2379
|
+
return {
|
|
2380
|
+
data: result.data,
|
|
2381
|
+
rows: result.data?.rows ?? [],
|
|
2382
|
+
totalItems: result.data?.totalItems ?? 0,
|
|
2383
|
+
debugAst: result.data?.debugAst,
|
|
2384
|
+
page: resolvedPage,
|
|
2385
|
+
pageSize: resolvedPageSize,
|
|
2386
|
+
error: result.error,
|
|
2387
|
+
isLoading: result.isLoading,
|
|
2388
|
+
isFetching: result.isFetching,
|
|
2389
|
+
isSuccess: result.isSuccess,
|
|
2390
|
+
isError: result.isError,
|
|
2391
|
+
status: result.status,
|
|
2392
|
+
refetch: result.refetch,
|
|
2393
|
+
reset: result.reset
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2000
2396
|
function resolveGetSession(authClient) {
|
|
2001
2397
|
if ("getSession" in authClient && typeof authClient.getSession === "function") {
|
|
2002
2398
|
return authClient.getSession;
|
|
@@ -2291,7 +2687,7 @@ function resolveNullishValue(mode) {
|
|
|
2291
2687
|
if (mode === "null") return null;
|
|
2292
2688
|
return "";
|
|
2293
2689
|
}
|
|
2294
|
-
function
|
|
2690
|
+
function isRecord4(value) {
|
|
2295
2691
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2296
2692
|
}
|
|
2297
2693
|
function isNullableColumn(model, key) {
|
|
@@ -2300,7 +2696,7 @@ function isNullableColumn(model, key) {
|
|
|
2300
2696
|
}
|
|
2301
2697
|
function toModelFormDefaults(model, values, options) {
|
|
2302
2698
|
const source = values;
|
|
2303
|
-
if (!
|
|
2699
|
+
if (!isRecord4(source)) {
|
|
2304
2700
|
return {};
|
|
2305
2701
|
}
|
|
2306
2702
|
const mode = options?.nullishMode ?? "empty-string";
|
|
@@ -2357,6 +2753,7 @@ exports.toModelFormDefaults = toModelFormDefaults;
|
|
|
2357
2753
|
exports.toModelPayload = toModelPayload;
|
|
2358
2754
|
exports.useAthenaGateway = useAthenaGateway;
|
|
2359
2755
|
exports.useAthenaQueryClient = useAthenaQueryClient;
|
|
2756
|
+
exports.useAthenaReadQuery = useAthenaReadQuery;
|
|
2360
2757
|
exports.useAthenaSessionClient = useAthenaSessionClient;
|
|
2361
2758
|
exports.useMutation = useMutation;
|
|
2362
2759
|
exports.useQuery = useQuery;
|