@xylex-group/athena 3.0.3 → 3.3.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.
Files changed (86) hide show
  1. package/README.md +1 -1
  2. package/dist/admin.cjs +55 -1
  3. package/dist/admin.cjs.map +1 -1
  4. package/dist/admin.d.cts +32 -8
  5. package/dist/admin.d.ts +32 -8
  6. package/dist/admin.js +54 -2
  7. package/dist/admin.js.map +1 -1
  8. package/dist/athena-auth-url-C1FbVmN6.d.cts +200 -0
  9. package/dist/athena-auth-url-C1FbVmN6.d.ts +200 -0
  10. package/dist/{athena-request-headers-C7Jy-c_D.d.ts → athena-request-headers-DzimbvOA.d.ts} +48 -200
  11. package/dist/{athena-request-headers-DujFFyMU.d.cts → athena-request-headers-Lr_m8xCV.d.cts} +48 -200
  12. package/dist/billing.cjs +1 -1
  13. package/dist/billing.cjs.map +1 -1
  14. package/dist/billing.js +1 -1
  15. package/dist/billing.js.map +1 -1
  16. package/dist/browser.cjs +912 -5
  17. package/dist/browser.cjs.map +1 -1
  18. package/dist/browser.d.cts +8 -7
  19. package/dist/browser.d.ts +8 -7
  20. package/dist/browser.js +881 -6
  21. package/dist/browser.js.map +1 -1
  22. package/dist/cli/index.cjs +7909 -7061
  23. package/dist/cli/index.cjs.map +1 -1
  24. package/dist/cli/index.d.cts +17 -10
  25. package/dist/cli/index.d.ts +17 -10
  26. package/dist/cli/index.js +7911 -7063
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/env.cjs +130 -0
  29. package/dist/env.cjs.map +1 -0
  30. package/dist/env.d.cts +70 -0
  31. package/dist/env.d.ts +70 -0
  32. package/dist/env.js +122 -0
  33. package/dist/env.js.map +1 -0
  34. package/dist/index.cjs +1570 -98
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +31 -8
  37. package/dist/index.d.ts +31 -8
  38. package/dist/index.js +1532 -100
  39. package/dist/index.js.map +1 -1
  40. package/dist/model-form-3Gr8rkdT.d.cts +281 -0
  41. package/dist/model-form-CotpEL7z.d.ts +281 -0
  42. package/dist/{module-CPG3ULxQ.d.cts → module-CQmOaDzP.d.cts} +4 -4
  43. package/dist/{module-BruTcxe0.d.ts → module-CWkUTcUc.d.ts} +4 -4
  44. package/dist/next/client.cjs +123 -7
  45. package/dist/next/client.cjs.map +1 -1
  46. package/dist/next/client.d.cts +4 -3
  47. package/dist/next/client.d.ts +4 -3
  48. package/dist/next/client.js +123 -7
  49. package/dist/next/client.js.map +1 -1
  50. package/dist/next/server.cjs +1130 -364
  51. package/dist/next/server.cjs.map +1 -1
  52. package/dist/next/server.d.cts +121 -8
  53. package/dist/next/server.d.ts +121 -8
  54. package/dist/next/server.js +1120 -365
  55. package/dist/next/server.js.map +1 -1
  56. package/dist/pipeline-BnRKO_Pd.d.cts +93 -0
  57. package/dist/pipeline-sWCmlFqu.d.ts +93 -0
  58. package/dist/{proxy-request-headers-m4D2Tduy.d.ts → proxy-request-headers-CttlcuRb.d.ts} +1 -1
  59. package/dist/{proxy-request-headers-DGxdoyA0.d.cts → proxy-request-headers-pIBSn1Fw.d.cts} +1 -1
  60. package/dist/react.cjs +672 -16
  61. package/dist/react.cjs.map +1 -1
  62. package/dist/react.d.cts +123 -8
  63. package/dist/react.d.ts +123 -8
  64. package/dist/react.js +671 -17
  65. package/dist/react.js.map +1 -1
  66. package/dist/schema-handlers-BtT_IQFi.d.cts +138 -0
  67. package/dist/schema-handlers-VjFDhIMw.d.ts +138 -0
  68. package/dist/social-providers.d.cts +1 -1
  69. package/dist/social-providers.d.ts +1 -1
  70. package/dist/{types-D6tZ9aoq.d.ts → types-BDX8zS7w.d.ts} +40 -1
  71. package/dist/{types-AOY-GLu8.d.cts → types-BVKpQmfY.d.cts} +11 -0
  72. package/dist/{types-AOY-GLu8.d.ts → types-BVKpQmfY.d.ts} +11 -0
  73. package/dist/{types-DFr2cL1N.d.cts → types-D-Am7YSd.d.cts} +40 -1
  74. package/dist/utils.cjs +30 -0
  75. package/dist/utils.cjs.map +1 -1
  76. package/dist/utils.d.cts +3 -2
  77. package/dist/utils.d.ts +3 -2
  78. package/dist/utils.js +30 -1
  79. package/dist/utils.js.map +1 -1
  80. package/dist/{v3-client-CWfZHcKL.d.cts → v3-client-G1SLeHRa.d.cts} +23 -1
  81. package/dist/{v3-client-DZp2NEhK.d.ts → v3-client-ao8BWQ8v.d.ts} +23 -1
  82. package/package.json +16 -2
  83. package/dist/model-form-Dh0sisdL.d.ts +0 -97
  84. package/dist/model-form-oOAJUVd4.d.cts +0 -97
  85. package/dist/pipeline-CIzV9f7b.d.cts +0 -8
  86. package/dist/pipeline-DNlc8Ayn.d.ts +0 -8
package/dist/react.js CHANGED
@@ -392,7 +392,7 @@ function buildAthenaRequestHeaders(input) {
392
392
 
393
393
  // package.json
394
394
  var package_default = {
395
- version: "3.0.3"
395
+ version: "3.3.0"
396
396
  };
397
397
 
398
398
  // src/sdk-version.ts
@@ -1043,7 +1043,8 @@ function stableSerialize(value, seen) {
1043
1043
  if (value === void 0) return "undefined";
1044
1044
  const valueType = typeof value;
1045
1045
  if (valueType === "string") return `"${value}"`;
1046
- if (valueType === "number") return Number.isFinite(value) ? String(value) : "null";
1046
+ if (valueType === "number")
1047
+ return Number.isFinite(value) ? String(value) : "null";
1047
1048
  if (valueType === "boolean") return value ? "true" : "false";
1048
1049
  if (valueType === "bigint") return `${String(value)}n`;
1049
1050
  if (valueType === "symbol") return `symbol:${String(value)}`;
@@ -1124,7 +1125,8 @@ async function runWithRetry(execute, options) {
1124
1125
  }
1125
1126
  function errorMessageFromUnknown(error) {
1126
1127
  if (typeof error === "string" && error.trim()) return error.trim();
1127
- if (error instanceof Error && error.message.trim()) return error.message.trim();
1128
+ if (error instanceof Error && error.message.trim())
1129
+ return error.message.trim();
1128
1130
  if (isRecord2(error)) {
1129
1131
  const messageCandidate = error.message ?? error.error;
1130
1132
  if (typeof messageCandidate === "string" && messageCandidate.trim()) {
@@ -1343,7 +1345,11 @@ var AthenaQueryClient = class {
1343
1345
  const key = this.getMutationKeyToken(mutationKey);
1344
1346
  const entry = this.ensureMutationEntry(key);
1345
1347
  entry.activeRequestId = ++this.requestCounter;
1346
- this.setMutationState(entry, createInitialMutationState(), "mutation_reset");
1348
+ this.setMutationState(
1349
+ entry,
1350
+ createInitialMutationState(),
1351
+ "mutation_reset"
1352
+ );
1347
1353
  }
1348
1354
  async executeQuery(input) {
1349
1355
  const entry = this.ensureQueryEntry(input.queryKeyToken);
@@ -1405,7 +1411,10 @@ var AthenaQueryClient = class {
1405
1411
  );
1406
1412
  }
1407
1413
  const rawResult = await input.queryFn();
1408
- const normalized = normalizeAthenaResult(rawResult, input.select);
1414
+ const normalized = normalizeAthenaResult(
1415
+ rawResult,
1416
+ input.select
1417
+ );
1409
1418
  if (normalized.error) {
1410
1419
  throw {
1411
1420
  __athenaNormalizedError: normalized.error,
@@ -1493,7 +1502,10 @@ var AthenaQueryClient = class {
1493
1502
  this.inflightQueries.delete(input.queryKeyToken);
1494
1503
  }
1495
1504
  });
1496
- this.inflightQueries.set(input.queryKeyToken, executionPromise);
1505
+ this.inflightQueries.set(
1506
+ input.queryKeyToken,
1507
+ executionPromise
1508
+ );
1497
1509
  return executionPromise;
1498
1510
  }
1499
1511
  async executeMutation(input) {
@@ -1539,7 +1551,10 @@ var AthenaQueryClient = class {
1539
1551
  );
1540
1552
  }
1541
1553
  const rawResult = await input.mutationFn(input.variables);
1542
- const normalized = normalizeAthenaResult(rawResult, input.select);
1554
+ const normalized = normalizeAthenaResult(
1555
+ rawResult,
1556
+ input.select
1557
+ );
1543
1558
  if (normalized.error) {
1544
1559
  throw {
1545
1560
  __athenaNormalizedError: normalized.error,
@@ -1976,6 +1991,430 @@ function useMutation(options) {
1976
1991
  lastRequest: snapshot.lastRequest
1977
1992
  };
1978
1993
  }
1994
+
1995
+ // src/query-debug-ast.ts
1996
+ var ATHENA_DEBUG_AST_KEY = "__athenaDebugAst";
1997
+ function getAthenaDebugAst(value) {
1998
+ if (!value || typeof value !== "object" && typeof value !== "function") {
1999
+ return null;
2000
+ }
2001
+ return value[ATHENA_DEBUG_AST_KEY] ?? null;
2002
+ }
2003
+
2004
+ // src/query/read-query.ts
2005
+ function normalizeAthenaReadQueryOrderBy(orderBy) {
2006
+ if (!orderBy) {
2007
+ return [];
2008
+ }
2009
+ const list = Array.isArray(orderBy) ? orderBy : [orderBy];
2010
+ return list.filter(
2011
+ (entry) => entry && typeof entry.column === "string" && entry.column.trim().length > 0
2012
+ );
2013
+ }
2014
+ function isRecord3(value) {
2015
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2016
+ }
2017
+ function flattenAthenaRowValue(row, column) {
2018
+ if (!column.relation) {
2019
+ return row[column.column];
2020
+ }
2021
+ const relationValue = row[column.relation.name];
2022
+ if (Array.isArray(relationValue)) {
2023
+ return relationValue.map((entry) => isRecord3(entry) ? entry[column.column] : void 0).filter((entry) => entry !== void 0);
2024
+ }
2025
+ if (isRecord3(relationValue)) {
2026
+ return relationValue[column.column];
2027
+ }
2028
+ return void 0;
2029
+ }
2030
+ function resolveFlatRowKey(row, index, preferredKey) {
2031
+ const preferredValue = preferredKey && preferredKey in row ? row[preferredKey] : void 0;
2032
+ if (preferredValue !== void 0 && preferredValue !== null && `${preferredValue}`.trim().length > 0) {
2033
+ return String(preferredValue);
2034
+ }
2035
+ for (const [key, value] of Object.entries(row)) {
2036
+ if (key === "__rowKey") {
2037
+ continue;
2038
+ }
2039
+ if (value === void 0 || value === null) {
2040
+ continue;
2041
+ }
2042
+ if (Array.isArray(value)) {
2043
+ if (value.length > 0) {
2044
+ return `${key}-${value.join("-")}`;
2045
+ }
2046
+ continue;
2047
+ }
2048
+ const nextValue = String(value).trim();
2049
+ if (nextValue.length > 0) {
2050
+ return nextValue;
2051
+ }
2052
+ }
2053
+ return `row-${index + 1}`;
2054
+ }
2055
+ function flattenAthenaReadQueryRows(rows, columns, preferredKey) {
2056
+ return rows.map((entry, index) => {
2057
+ const sourceRow = isRecord3(entry) ? entry : {};
2058
+ const flatRow = columns.reduce(
2059
+ (currentRow, column) => {
2060
+ currentRow[column.key] = flattenAthenaRowValue(sourceRow, column);
2061
+ return currentRow;
2062
+ },
2063
+ { __rowKey: "" }
2064
+ );
2065
+ flatRow.__rowKey = resolveFlatRowKey(flatRow, index, preferredKey);
2066
+ return flatRow;
2067
+ });
2068
+ }
2069
+ function buildAthenaReadQuerySelectString(columns) {
2070
+ const baseColumns = columns.filter((column) => !column.relation).map((column) => column.column);
2071
+ const relationGroups = /* @__PURE__ */ new Map();
2072
+ for (const column of columns) {
2073
+ if (!column.relation) {
2074
+ continue;
2075
+ }
2076
+ const groupKey = [
2077
+ column.relation.name,
2078
+ column.relation.schema ?? "",
2079
+ column.relation.table
2080
+ ].join(":");
2081
+ const existingGroup = relationGroups.get(groupKey);
2082
+ if (existingGroup) {
2083
+ if (!existingGroup.columns.includes(column.column)) {
2084
+ existingGroup.columns.push(column.column);
2085
+ }
2086
+ continue;
2087
+ }
2088
+ relationGroups.set(groupKey, {
2089
+ columns: [column.column],
2090
+ relation: column.relation
2091
+ });
2092
+ }
2093
+ const relationColumns = [...relationGroups.values()].map(
2094
+ ({ columns: relationColumns2, relation }) => {
2095
+ const relationTarget = relation.schema ? `${relation.schema}.${relation.table}` : relation.table;
2096
+ return `${relation.name}:${relationTarget}(${relationColumns2.join(",")})`;
2097
+ }
2098
+ );
2099
+ return [...baseColumns, ...relationColumns].join(",");
2100
+ }
2101
+ function buildAthenaReadQueryFindManySelect(columns) {
2102
+ const select = {};
2103
+ for (const column of columns) {
2104
+ if (!column.relation) {
2105
+ select[column.column] = true;
2106
+ continue;
2107
+ }
2108
+ const existingRelation = select[column.relation.name];
2109
+ if (existingRelation && existingRelation !== true && isRecord3(existingRelation.select)) {
2110
+ existingRelation.select[column.column] = true;
2111
+ continue;
2112
+ }
2113
+ select[column.relation.name] = {
2114
+ ...column.relation.schema ? { schema: column.relation.schema } : {},
2115
+ select: {
2116
+ [column.column]: true
2117
+ }
2118
+ };
2119
+ }
2120
+ return select;
2121
+ }
2122
+ function buildAthenaReadQueryFindManyWhere(filters) {
2123
+ if (!filters?.length) {
2124
+ return;
2125
+ }
2126
+ return filters.reduce(
2127
+ (where, filter) => {
2128
+ const operator = filter.operator ?? "eq";
2129
+ where[filter.column] = operator === "eq" ? filter.value : { [operator]: filter.value };
2130
+ return where;
2131
+ },
2132
+ {}
2133
+ );
2134
+ }
2135
+ function buildAthenaReadQueryFindManyOrderBy(orderBy) {
2136
+ const normalized = normalizeAthenaReadQueryOrderBy(orderBy);
2137
+ if (normalized.length === 0) {
2138
+ return;
2139
+ }
2140
+ if (normalized.length === 1) {
2141
+ const primary = normalized[0];
2142
+ if (!primary) {
2143
+ return;
2144
+ }
2145
+ return {
2146
+ ascending: primary.direction !== "desc",
2147
+ column: primary.column
2148
+ };
2149
+ }
2150
+ return Object.fromEntries(
2151
+ normalized.map((entry) => [
2152
+ entry.column,
2153
+ entry.direction === "desc" ? "desc" : "asc"
2154
+ ])
2155
+ );
2156
+ }
2157
+ function applyAthenaReadQueryFilters(queryBuilder, filters) {
2158
+ if (!filters?.length) {
2159
+ return queryBuilder;
2160
+ }
2161
+ return filters.reduce((currentBuilder, filter) => {
2162
+ const operator = filter.operator ?? "eq";
2163
+ const builderMethod = currentBuilder[operator];
2164
+ if (typeof builderMethod !== "function") {
2165
+ return currentBuilder;
2166
+ }
2167
+ return builderMethod.call(currentBuilder, filter.column, filter.value);
2168
+ }, queryBuilder);
2169
+ }
2170
+ function applyAthenaReadQuerySelectOrder(queryBuilder, orderBy) {
2171
+ const normalized = normalizeAthenaReadQueryOrderBy(orderBy);
2172
+ if (normalized.length === 0) {
2173
+ return queryBuilder;
2174
+ }
2175
+ return normalized.reduce(
2176
+ (builder, entry) => builder.order(entry.column, {
2177
+ ascending: entry.direction !== "desc"
2178
+ }),
2179
+ queryBuilder
2180
+ );
2181
+ }
2182
+ function clampAthenaReadQueryTotalItems(totalItems, limit) {
2183
+ if (!limit || limit < 1) {
2184
+ return totalItems;
2185
+ }
2186
+ return Math.min(totalItems, limit);
2187
+ }
2188
+ function resolveCountValue(...candidates) {
2189
+ for (const candidate of candidates) {
2190
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
2191
+ return Math.max(0, Math.trunc(candidate));
2192
+ }
2193
+ }
2194
+ return 0;
2195
+ }
2196
+ function resolveTotalItemsFromPage({
2197
+ countCandidates,
2198
+ limit,
2199
+ page,
2200
+ pageSize,
2201
+ rowCount
2202
+ }) {
2203
+ const exactCount = resolveCountValue(...countCandidates);
2204
+ if (exactCount > 0) {
2205
+ return clampAthenaReadQueryTotalItems(exactCount, limit);
2206
+ }
2207
+ if (rowCount > 0) {
2208
+ const base = (page - 1) * pageSize + rowCount;
2209
+ const synthetic = rowCount >= pageSize ? base + 1 : base;
2210
+ return clampAthenaReadQueryTotalItems(synthetic, limit);
2211
+ }
2212
+ return clampAthenaReadQueryTotalItems(exactCount, limit);
2213
+ }
2214
+ function resolveAthenaReadQueryPageFetch({
2215
+ page,
2216
+ pageSize,
2217
+ limit
2218
+ }) {
2219
+ const safePage = Math.max(1, Math.trunc(page) || 1);
2220
+ const safePageSize = Math.max(1, Math.trunc(pageSize) || 1);
2221
+ if (!limit || limit < 1) {
2222
+ return { page: safePage, pageSize: safePageSize, shouldFetch: true };
2223
+ }
2224
+ const totalCap = Math.trunc(limit);
2225
+ const offset = (safePage - 1) * safePageSize;
2226
+ if (offset >= totalCap) {
2227
+ return { page: safePage, pageSize: safePageSize, shouldFetch: false };
2228
+ }
2229
+ return {
2230
+ page: safePage,
2231
+ pageSize: Math.min(safePageSize, totalCap - offset),
2232
+ shouldFetch: true
2233
+ };
2234
+ }
2235
+ async function executeAthenaReadQuery({
2236
+ client,
2237
+ page,
2238
+ pageSize,
2239
+ query
2240
+ }) {
2241
+ const db = client.db;
2242
+ const baseBuilder = db.from(query.table, {
2243
+ schema: query.schema
2244
+ });
2245
+ const countBuilder = applyAthenaReadQueryFilters(
2246
+ db.from(query.table, { schema: query.schema }),
2247
+ query.filters
2248
+ );
2249
+ const countResult = await countBuilder.select(query.countColumn, {
2250
+ count: "exact",
2251
+ head: true
2252
+ });
2253
+ const pageFetch = resolveAthenaReadQueryPageFetch({
2254
+ limit: query.limit,
2255
+ page,
2256
+ pageSize
2257
+ });
2258
+ if (!pageFetch.shouldFetch) {
2259
+ return {
2260
+ rows: [],
2261
+ totalItems: resolveTotalItemsFromPage({
2262
+ countCandidates: [countResult.count],
2263
+ limit: query.limit,
2264
+ page: pageFetch.page,
2265
+ pageSize,
2266
+ rowCount: 0
2267
+ })
2268
+ };
2269
+ }
2270
+ if ((query.mode ?? "findMany") === "select") {
2271
+ const selectBuilder = applyAthenaReadQuerySelectOrder(
2272
+ applyAthenaReadQueryFilters(baseBuilder, query.filters),
2273
+ query.orderBy
2274
+ );
2275
+ const result2 = await selectBuilder.currentPage(pageFetch.page).pageSize(pageFetch.pageSize).select(buildAthenaReadQuerySelectString(query.columns), {
2276
+ count: "exact"
2277
+ });
2278
+ const rows2 = flattenAthenaReadQueryRows(
2279
+ Array.isArray(result2.data) ? result2.data : [],
2280
+ query.columns,
2281
+ query.rowKey
2282
+ );
2283
+ return {
2284
+ debugAst: getAthenaDebugAst(result2) ?? void 0,
2285
+ rows: rows2,
2286
+ totalItems: resolveTotalItemsFromPage({
2287
+ countCandidates: [countResult.count, result2.count],
2288
+ limit: query.limit,
2289
+ page: pageFetch.page,
2290
+ pageSize,
2291
+ rowCount: rows2.length
2292
+ })
2293
+ };
2294
+ }
2295
+ const findManyOrderBy = buildAthenaReadQueryFindManyOrderBy(query.orderBy);
2296
+ const findManyOptions = {
2297
+ ...findManyOrderBy ? { orderBy: findManyOrderBy } : {},
2298
+ select: buildAthenaReadQueryFindManySelect(query.columns),
2299
+ ...query.filters?.length ? { where: buildAthenaReadQueryFindManyWhere(query.filters) } : {}
2300
+ };
2301
+ const result = await baseBuilder.currentPage(pageFetch.page).pageSize(pageFetch.pageSize).findMany(findManyOptions);
2302
+ const rows = flattenAthenaReadQueryRows(
2303
+ Array.isArray(result.data) ? result.data : [],
2304
+ query.columns,
2305
+ query.rowKey
2306
+ );
2307
+ return {
2308
+ debugAst: getAthenaDebugAst(result) ?? void 0,
2309
+ rows,
2310
+ totalItems: resolveTotalItemsFromPage({
2311
+ countCandidates: [countResult.count, result.count],
2312
+ limit: query.limit,
2313
+ page: pageFetch.page,
2314
+ pageSize,
2315
+ rowCount: rows.length
2316
+ })
2317
+ };
2318
+ }
2319
+
2320
+ // src/react/use-athena-read-query.ts
2321
+ var DEFAULT_PAGE = 1;
2322
+ var DEFAULT_PAGE_SIZE = 10;
2323
+ function isReadQueryRunnable(query) {
2324
+ return query.table.trim().length > 0 && query.columns.length > 0 && query.countColumn.trim().length > 0;
2325
+ }
2326
+ function useAthenaReadQuery({
2327
+ client,
2328
+ query,
2329
+ page = DEFAULT_PAGE,
2330
+ pageSize = DEFAULT_PAGE_SIZE,
2331
+ enabled = true,
2332
+ queryKey,
2333
+ queryKeyPrefix,
2334
+ refetchOnMount,
2335
+ refetchOnWindowFocus,
2336
+ refetchOnReconnect,
2337
+ retry
2338
+ }) {
2339
+ const resolvedPage = page > 0 ? Math.trunc(page) : DEFAULT_PAGE;
2340
+ const resolvedPageSize = pageSize > 0 ? Math.trunc(pageSize) : DEFAULT_PAGE_SIZE;
2341
+ const queryEnabled = enabled && !!client && isReadQueryRunnable(query);
2342
+ const defaultQueryKey = useMemo(
2343
+ () => [
2344
+ "athena",
2345
+ "read-query",
2346
+ query.mode ?? "findMany",
2347
+ query.table,
2348
+ query.schema,
2349
+ query.columns,
2350
+ query.filters,
2351
+ query.limit,
2352
+ query.orderBy,
2353
+ query.rowKey,
2354
+ query.countColumn,
2355
+ resolvedPage,
2356
+ resolvedPageSize
2357
+ ],
2358
+ [
2359
+ query.columns,
2360
+ query.countColumn,
2361
+ query.filters,
2362
+ query.limit,
2363
+ query.mode,
2364
+ query.orderBy,
2365
+ query.rowKey,
2366
+ query.schema,
2367
+ query.table,
2368
+ resolvedPage,
2369
+ resolvedPageSize
2370
+ ]
2371
+ );
2372
+ const resolvedQueryKey = useMemo(() => {
2373
+ if (queryKey !== void 0) {
2374
+ return queryKey;
2375
+ }
2376
+ if (queryKeyPrefix !== void 0) {
2377
+ const prefix = Array.isArray(queryKeyPrefix) ? queryKeyPrefix : [queryKeyPrefix];
2378
+ return [...prefix, ...defaultQueryKey];
2379
+ }
2380
+ return defaultQueryKey;
2381
+ }, [defaultQueryKey, queryKey, queryKeyPrefix]);
2382
+ const result = useQuery({
2383
+ enabled: queryEnabled,
2384
+ queryKey: resolvedQueryKey,
2385
+ queryFn: async () => {
2386
+ if (!client) {
2387
+ throw new Error("Athena client is required to run the read query.");
2388
+ }
2389
+ return executeAthenaReadQuery({
2390
+ client,
2391
+ page: resolvedPage,
2392
+ pageSize: resolvedPageSize,
2393
+ query
2394
+ });
2395
+ },
2396
+ refetchOnMount,
2397
+ refetchOnWindowFocus,
2398
+ refetchOnReconnect,
2399
+ retry
2400
+ });
2401
+ return {
2402
+ data: result.data,
2403
+ rows: result.data?.rows ?? [],
2404
+ totalItems: result.data?.totalItems ?? 0,
2405
+ debugAst: result.data?.debugAst,
2406
+ page: resolvedPage,
2407
+ pageSize: resolvedPageSize,
2408
+ error: result.error,
2409
+ isLoading: result.isLoading,
2410
+ isFetching: result.isFetching,
2411
+ isSuccess: result.isSuccess,
2412
+ isError: result.isError,
2413
+ status: result.status,
2414
+ refetch: result.refetch,
2415
+ reset: result.reset
2416
+ };
2417
+ }
1979
2418
  function resolveGetSession(authClient) {
1980
2419
  if ("getSession" in authClient && typeof authClient.getSession === "function") {
1981
2420
  return authClient.getSession;
@@ -1983,7 +2422,16 @@ function resolveGetSession(authClient) {
1983
2422
  if ("auth" in authClient && authClient.auth && typeof authClient.auth.getSession === "function") {
1984
2423
  return authClient.auth.getSession;
1985
2424
  }
1986
- throw new Error("useSession requires an auth-capable client (createClient(...).auth)");
2425
+ throw new Error(
2426
+ "useSession requires an auth-capable client (createClient(...).auth)"
2427
+ );
2428
+ }
2429
+ function toFallbackErrorDetails(code, message, status) {
2430
+ return {
2431
+ code,
2432
+ message,
2433
+ status
2434
+ };
1987
2435
  }
1988
2436
  function useSession(authClient, options = {}) {
1989
2437
  const enabled = options.enabled ?? true;
@@ -2001,11 +2449,6 @@ function useSession(authClient, options = {}) {
2001
2449
  useEffect(() => {
2002
2450
  dataRef.current = data;
2003
2451
  }, [data]);
2004
- const toFallbackErrorDetails = (code, message, status) => ({
2005
- code,
2006
- message,
2007
- status
2008
- });
2009
2452
  const runFetch = useCallback(async () => {
2010
2453
  const requestId = ++requestIdRef.current;
2011
2454
  const hasData = dataRef.current !== null;
@@ -2068,6 +2511,211 @@ function useSession(authClient, options = {}) {
2068
2511
  refetch
2069
2512
  };
2070
2513
  }
2514
+
2515
+ // src/admin/index.ts
2516
+ function resolveAdminPermissionClient(client) {
2517
+ if (!client || typeof client !== "object") {
2518
+ return null;
2519
+ }
2520
+ const record = client;
2521
+ const nestedAuth = record.auth;
2522
+ if (nestedAuth && typeof nestedAuth === "object" && nestedAuth !== null && "admin" in nestedAuth) {
2523
+ return client;
2524
+ }
2525
+ if ("admin" in record) {
2526
+ return { auth: client };
2527
+ }
2528
+ return null;
2529
+ }
2530
+ function buildAdminAuthFetchOptions(credentials = {}) {
2531
+ const cookie = credentials.cookie?.trim() || void 0;
2532
+ const bearerToken = credentials.bearerToken?.trim() || void 0;
2533
+ const headers = {};
2534
+ if (cookie) {
2535
+ headers.cookie = cookie;
2536
+ }
2537
+ if (bearerToken) {
2538
+ headers.authorization = `Bearer ${bearerToken}`;
2539
+ }
2540
+ return {
2541
+ credentials: "include",
2542
+ ...bearerToken ? { bearerToken } : {},
2543
+ ...Object.keys(headers).length > 0 ? { headers } : {}
2544
+ };
2545
+ }
2546
+ function hasAdminRole(session) {
2547
+ const role = session?.user?.role;
2548
+ if (!role) {
2549
+ return false;
2550
+ }
2551
+ return role.split(",").map((item) => item.trim().toLowerCase()).includes("admin");
2552
+ }
2553
+ function mergeAdminFetchOptions(input) {
2554
+ const fromCredentials = input.credentials ? buildAdminAuthFetchOptions(input.credentials) : void 0;
2555
+ const explicit = input.fetchOptions;
2556
+ if (!fromCredentials && !explicit) {
2557
+ return void 0;
2558
+ }
2559
+ if (!fromCredentials) {
2560
+ return explicit;
2561
+ }
2562
+ if (!explicit) {
2563
+ return fromCredentials;
2564
+ }
2565
+ return {
2566
+ ...fromCredentials,
2567
+ ...explicit,
2568
+ headers: {
2569
+ ...fromCredentials.headers ?? {},
2570
+ ...explicit.headers ?? {}
2571
+ }
2572
+ };
2573
+ }
2574
+ async function hasAdminPermission(client, input) {
2575
+ if (!input.session?.user?.id) {
2576
+ return false;
2577
+ }
2578
+ if (input.allowRoleBypass !== false && hasAdminRole(input.session)) {
2579
+ return true;
2580
+ }
2581
+ const fetchOptions = mergeAdminFetchOptions(input);
2582
+ const result = await client.auth.admin.hasPermission(
2583
+ {
2584
+ permission: input.permission,
2585
+ permissions: input.permissions,
2586
+ ...fetchOptions ? { fetchOptions } : {}
2587
+ },
2588
+ input.requestOptions
2589
+ );
2590
+ return Boolean(result.ok && result.data?.success);
2591
+ }
2592
+
2593
+ // src/react/use-admin-permission.ts
2594
+ var DEFAULT_ADMIN_PERMISSIONS = [
2595
+ "admin:read"
2596
+ ];
2597
+ function serializePermissions(permissions, permission) {
2598
+ return JSON.stringify({
2599
+ permission: permission ?? null,
2600
+ permissions: permissions ?? DEFAULT_ADMIN_PERMISSIONS
2601
+ });
2602
+ }
2603
+ function useAdminPermission(client, options = {}) {
2604
+ const enabled = options.enabled ?? true;
2605
+ const sessionProvided = "session" in options;
2606
+ const sessionFromOptions = sessionProvided ? options.session ?? null : void 0;
2607
+ const permissionsKey = serializePermissions(options.permissions, options.permission);
2608
+ const allowRoleBypass = options.allowRoleBypass;
2609
+ const fetchOptions = options.fetchOptions;
2610
+ const requestOptions = options.requestOptions;
2611
+ const optionsRef = useRef(options);
2612
+ optionsRef.current = options;
2613
+ const sessionState = useSession(client, {
2614
+ ...options.sessionOptions,
2615
+ enabled: enabled && !sessionProvided && !!client
2616
+ });
2617
+ const session = sessionProvided ? sessionFromOptions ?? null : sessionState.data;
2618
+ const sessionPending = !sessionProvided && sessionState.isPending;
2619
+ const sessionUserId = session?.user?.id ?? null;
2620
+ const sessionRole = session?.user?.role ?? null;
2621
+ const [allowed, setAllowed] = useState(false);
2622
+ const [error, setError] = useState(null);
2623
+ const [isChecking, setIsChecking] = useState(enabled);
2624
+ const requestIdRef = useRef(0);
2625
+ const mountedRef = useRef(true);
2626
+ const runCheck = useCallback(async () => {
2627
+ const requestId = ++requestIdRef.current;
2628
+ const current = optionsRef.current;
2629
+ const permissions = current.permissions ?? DEFAULT_ADMIN_PERMISSIONS;
2630
+ if (!enabled || !client) {
2631
+ if (mountedRef.current && requestId === requestIdRef.current) {
2632
+ setAllowed(false);
2633
+ setError(null);
2634
+ setIsChecking(false);
2635
+ }
2636
+ return false;
2637
+ }
2638
+ setIsChecking(true);
2639
+ try {
2640
+ const permissionClient = resolveAdminPermissionClient(client);
2641
+ if (!permissionClient) {
2642
+ throw new Error(
2643
+ "useAdminPermission requires an Athena client with auth.admin (createClient(...) or auth bindings)"
2644
+ );
2645
+ }
2646
+ const resolvedSession = sessionProvided ? current.session ?? null : sessionState.data;
2647
+ const nextAllowed = await hasAdminPermission(permissionClient, {
2648
+ session: resolvedSession,
2649
+ permissions,
2650
+ permission: current.permission,
2651
+ allowRoleBypass: current.allowRoleBypass,
2652
+ fetchOptions: current.fetchOptions,
2653
+ requestOptions: current.requestOptions
2654
+ });
2655
+ if (!mountedRef.current || requestId !== requestIdRef.current) {
2656
+ return nextAllowed;
2657
+ }
2658
+ setAllowed(nextAllowed);
2659
+ setError(null);
2660
+ return nextAllowed;
2661
+ } catch (checkError) {
2662
+ if (!mountedRef.current || requestId !== requestIdRef.current) {
2663
+ return false;
2664
+ }
2665
+ const nextError = checkError instanceof Error ? checkError : new Error("Failed to resolve admin permission");
2666
+ setAllowed(false);
2667
+ setError(nextError);
2668
+ return false;
2669
+ } finally {
2670
+ if (mountedRef.current && requestId === requestIdRef.current) {
2671
+ setIsChecking(false);
2672
+ }
2673
+ }
2674
+ }, [client, enabled, sessionProvided, sessionState.data]);
2675
+ useEffect(() => {
2676
+ mountedRef.current = true;
2677
+ return () => {
2678
+ mountedRef.current = false;
2679
+ };
2680
+ }, []);
2681
+ useEffect(() => {
2682
+ if (!enabled) {
2683
+ setAllowed(false);
2684
+ setError(null);
2685
+ setIsChecking(false);
2686
+ return;
2687
+ }
2688
+ if (!sessionProvided && sessionState.isPending) {
2689
+ setIsChecking(true);
2690
+ return;
2691
+ }
2692
+ void runCheck();
2693
+ }, [
2694
+ allowRoleBypass,
2695
+ enabled,
2696
+ fetchOptions,
2697
+ permissionsKey,
2698
+ requestOptions,
2699
+ runCheck,
2700
+ sessionPending,
2701
+ sessionProvided,
2702
+ sessionRole,
2703
+ sessionUserId
2704
+ ]);
2705
+ const refetch = useCallback(async () => {
2706
+ if (!sessionProvided) {
2707
+ await sessionState.refetch();
2708
+ }
2709
+ return await runCheck();
2710
+ }, [runCheck, sessionProvided, sessionState]);
2711
+ return {
2712
+ allowed,
2713
+ isPending: enabled && (sessionPending || isChecking),
2714
+ error,
2715
+ session,
2716
+ refetch
2717
+ };
2718
+ }
2071
2719
  function useAthenaSessionClient(baseClient, options = {}) {
2072
2720
  const sessionState = useSession(baseClient, options);
2073
2721
  const scopedClient = useMemo(
@@ -2172,7 +2820,13 @@ function isStorageUploadInput(input) {
2172
2820
  return Boolean(input) && typeof input === "object" && "files" in input && "s3_id" in input;
2173
2821
  }
2174
2822
  function useStorageFiles(options) {
2175
- const { storage, input, enabled = true, callOptions, refreshIntervalMs } = options;
2823
+ const {
2824
+ storage,
2825
+ input,
2826
+ enabled = true,
2827
+ callOptions,
2828
+ refreshIntervalMs
2829
+ } = options;
2176
2830
  const [data, setData] = React.useState(null);
2177
2831
  const [loading, setLoading] = React.useState(false);
2178
2832
  const [error, setError] = React.useState(null);
@@ -2270,7 +2924,7 @@ function resolveNullishValue(mode) {
2270
2924
  if (mode === "null") return null;
2271
2925
  return "";
2272
2926
  }
2273
- function isRecord3(value) {
2927
+ function isRecord4(value) {
2274
2928
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2275
2929
  }
2276
2930
  function isNullableColumn(model, key) {
@@ -2279,7 +2933,7 @@ function isNullableColumn(model, key) {
2279
2933
  }
2280
2934
  function toModelFormDefaults(model, values, options) {
2281
2935
  const source = values;
2282
- if (!isRecord3(source)) {
2936
+ if (!isRecord4(source)) {
2283
2937
  return {};
2284
2938
  }
2285
2939
  const mode = options?.nullishMode ?? "empty-string";
@@ -2325,6 +2979,6 @@ function createModelFormAdapter(model) {
2325
2979
  };
2326
2980
  }
2327
2981
 
2328
- export { AthenaGatewayError, AthenaQueryClient, AthenaQueryClientProvider, attachStateAdapter, createAthenaQueryClient, createModelFormAdapter, isAthenaGatewayError, toModelFormDefaults, toModelPayload, useAthenaGateway, useAthenaQueryClient, useAthenaSessionClient, useMutation, useQuery, useSession, useStorageFileDelete, useStorageFiles, useStorageUpload };
2982
+ export { AthenaGatewayError, AthenaQueryClient, AthenaQueryClientProvider, attachStateAdapter, createAthenaQueryClient, createModelFormAdapter, isAthenaGatewayError, toModelFormDefaults, toModelPayload, useAdminPermission, useAthenaGateway, useAthenaQueryClient, useAthenaReadQuery, useAthenaSessionClient, useMutation, useQuery, useSession, useStorageFileDelete, useStorageFiles, useStorageUpload };
2329
2983
  //# sourceMappingURL=react.js.map
2330
2984
  //# sourceMappingURL=react.js.map