@lunora/client 1.0.0-alpha.16 → 1.0.0-alpha.18

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/LICENSE.md CHANGED
@@ -103,3 +103,9 @@ Unless required by applicable law or agreed to in writing, software distributed
103
103
  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
104
  CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
105
  specific language governing permissions and limitations under the License.
106
+
107
+ <!-- DEPENDENCIES -->
108
+ <!-- /DEPENDENCIES -->
109
+
110
+ <!-- TYPE_DEPENDENCIES -->
111
+ <!-- /TYPE_DEPENDENCIES -->
@@ -1,4 +1,4 @@
1
- import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-CPMaTnsC.mjs";
1
+ import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-Dy4neKF6.mjs";
2
2
  import '@lunora/runtime';
3
3
  interface IdentityStore {
4
4
  /** Read the current resolved user, or `null` when signed out / not yet resolved. */
@@ -1,4 +1,4 @@
1
- import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-CPMaTnsC.js";
1
+ import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-Dy4neKF6.js";
2
2
  import '@lunora/runtime';
3
3
  interface IdentityStore {
4
4
  /** Read the current resolved user, or `null` when signed out / not yet resolved. */
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-CPMaTnsC.mjs";
2
- export { type e as BatchSlot, C as CONFLICT_ERROR_CODE, type f as CachedQuery, type g as ClientMessage, type h as ClientShapeSubscribeMessage, type i as ClientShapeUnsubscribeMessage, type j as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type k as FunctionArgumentDescriptor, type l as FunctionDescriptor, type G as GlobalFacetResult, type m as GlobalFacetValue, type n as GlobalFilterClause, type o as GlobalTableInfo, type p as GlobalTablePage, L as LunoraClient, type q as LunoraClientError, type r as LunoraClientOptions, type s as LunoraErrorCode, type t as MutationSettledEvent, type u as OptimisticLocalStore, type v as OptimisticUpdate, type w as OutboxMutation, type x as OutboxSink, type y as PersistedMutation, type P as Preloaded, type z as RowOp, type E as RpcEnvelope, type H as RpcResponseBody, type I as ScheduleRecord, type J as SchedulerPoolStatus, type K as SchedulerStatus, type N as ServerMessage, type T as ServerPokeEndMessage, type V as ServerPokePartMessage, type W as ServerPokeStartMessage, type X as ShardTrafficEntry, type Y as ShardTrafficResult, type Z as StorageListPage, type _ as StorageObject, type $ as StreamHandle, type a0 as StreamIterable, type a1 as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, a2 as SubscriptionRegistry, type a3 as SubscriptionState, type a4 as SyncWatermark, type a as Unsubscribe, type U as User, type a5 as WorkflowInstanceAction, type a6 as WorkflowInstanceDetail, type a7 as WorkflowInstancePage, type a8 as WorkflowInstanceStatus, type a9 as WorkflowInstanceSummary, type aa as WorkflowStepDetail, ab as createLocalStore, ac as createStream, ad as getErrorCode, ae as getRetryAfterMs, af as isConflictError, ag as isForbiddenError, ah as isRateLimitedError, ai as isUnauthorizedError } from "./packem_shared/lunora-client.d-CPMaTnsC.mjs";
3
- export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-Bl3z1rPo.mjs";
4
- export type { AuthCapabilities, AuthImpersonation, AuthPage, AuthSession, AuthUser, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
1
+ import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-Dy4neKF6.mjs";
2
+ export { type e as BatchSlot, C as CONFLICT_ERROR_CODE, type f as CachedQuery, type g as ClientMessage, type h as ClientShapeSubscribeMessage, type i as ClientShapeUnsubscribeMessage, type j as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type k as FunctionArgumentDescriptor, type l as FunctionDescriptor, type G as GlobalFacetResult, type m as GlobalFacetValue, type n as GlobalFilterClause, type o as GlobalTableInfo, type p as GlobalTablePage, L as LunoraClient, type q as LunoraClientError, type r as LunoraClientOptions, type s as LunoraErrorCode, type t as MutationSettledEvent, type u as OptimisticLocalStore, type v as OptimisticUpdate, type w as OutboxMutation, type x as OutboxSink, type y as PersistedMutation, type P as Preloaded, type z as RowOp, type E as RpcEnvelope, type H as RpcResponseBody, type I as ScheduleRecord, type J as SchedulerPoolStatus, type K as SchedulerStatus, type N as ServerMessage, type T as ServerPokeEndMessage, type V as ServerPokePartMessage, type W as ServerPokeStartMessage, type X as ShardTrafficEntry, type Y as ShardTrafficResult, type Z as StorageListPage, type _ as StorageObject, type $ as StreamHandle, type a0 as StreamIterable, type a1 as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, a2 as SubscriptionRegistry, type a3 as SubscriptionState, type a4 as SyncWatermark, type a as Unsubscribe, type U as User, type a5 as WorkflowInstanceAction, type a6 as WorkflowInstanceDetail, type a7 as WorkflowInstancePage, type a8 as WorkflowInstanceStatus, type a9 as WorkflowInstanceSummary, type aa as WorkflowStepDetail, ab as createLocalStore, ac as createStream, ad as getErrorCode, ae as getRetryAfterMs, af as isConflictError, ag as isForbiddenError, ah as isRateLimitedError, ai as isUnauthorizedError } from "./packem_shared/lunora-client.d-Dy4neKF6.mjs";
3
+ export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-BQaCmS5J.mjs";
4
+ export type { AuthCapabilities, AuthConfigInfo, AuthImpersonation, AuthPage, AuthSession, AuthUser, AuthUserFieldSpec, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
5
5
  /**
6
6
  * The slice of React Native's `AsyncStorage` (or any async key/value store —
7
7
  * Expo `SecureStore`, a wrapped `localForage`, an in-memory map in tests) this
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-CPMaTnsC.js";
2
- export { type e as BatchSlot, C as CONFLICT_ERROR_CODE, type f as CachedQuery, type g as ClientMessage, type h as ClientShapeSubscribeMessage, type i as ClientShapeUnsubscribeMessage, type j as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type k as FunctionArgumentDescriptor, type l as FunctionDescriptor, type G as GlobalFacetResult, type m as GlobalFacetValue, type n as GlobalFilterClause, type o as GlobalTableInfo, type p as GlobalTablePage, L as LunoraClient, type q as LunoraClientError, type r as LunoraClientOptions, type s as LunoraErrorCode, type t as MutationSettledEvent, type u as OptimisticLocalStore, type v as OptimisticUpdate, type w as OutboxMutation, type x as OutboxSink, type y as PersistedMutation, type P as Preloaded, type z as RowOp, type E as RpcEnvelope, type H as RpcResponseBody, type I as ScheduleRecord, type J as SchedulerPoolStatus, type K as SchedulerStatus, type N as ServerMessage, type T as ServerPokeEndMessage, type V as ServerPokePartMessage, type W as ServerPokeStartMessage, type X as ShardTrafficEntry, type Y as ShardTrafficResult, type Z as StorageListPage, type _ as StorageObject, type $ as StreamHandle, type a0 as StreamIterable, type a1 as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, a2 as SubscriptionRegistry, type a3 as SubscriptionState, type a4 as SyncWatermark, type a as Unsubscribe, type U as User, type a5 as WorkflowInstanceAction, type a6 as WorkflowInstanceDetail, type a7 as WorkflowInstancePage, type a8 as WorkflowInstanceStatus, type a9 as WorkflowInstanceSummary, type aa as WorkflowStepDetail, ab as createLocalStore, ac as createStream, ad as getErrorCode, ae as getRetryAfterMs, af as isConflictError, ag as isForbiddenError, ah as isRateLimitedError, ai as isUnauthorizedError } from "./packem_shared/lunora-client.d-CPMaTnsC.js";
3
- export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-DH0CqSxy.js";
4
- export type { AuthCapabilities, AuthImpersonation, AuthPage, AuthSession, AuthUser, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
1
+ import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-Dy4neKF6.js";
2
+ export { type e as BatchSlot, C as CONFLICT_ERROR_CODE, type f as CachedQuery, type g as ClientMessage, type h as ClientShapeSubscribeMessage, type i as ClientShapeUnsubscribeMessage, type j as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type k as FunctionArgumentDescriptor, type l as FunctionDescriptor, type G as GlobalFacetResult, type m as GlobalFacetValue, type n as GlobalFilterClause, type o as GlobalTableInfo, type p as GlobalTablePage, L as LunoraClient, type q as LunoraClientError, type r as LunoraClientOptions, type s as LunoraErrorCode, type t as MutationSettledEvent, type u as OptimisticLocalStore, type v as OptimisticUpdate, type w as OutboxMutation, type x as OutboxSink, type y as PersistedMutation, type P as Preloaded, type z as RowOp, type E as RpcEnvelope, type H as RpcResponseBody, type I as ScheduleRecord, type J as SchedulerPoolStatus, type K as SchedulerStatus, type N as ServerMessage, type T as ServerPokeEndMessage, type V as ServerPokePartMessage, type W as ServerPokeStartMessage, type X as ShardTrafficEntry, type Y as ShardTrafficResult, type Z as StorageListPage, type _ as StorageObject, type $ as StreamHandle, type a0 as StreamIterable, type a1 as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, a2 as SubscriptionRegistry, type a3 as SubscriptionState, type a4 as SyncWatermark, type a as Unsubscribe, type U as User, type a5 as WorkflowInstanceAction, type a6 as WorkflowInstanceDetail, type a7 as WorkflowInstancePage, type a8 as WorkflowInstanceStatus, type a9 as WorkflowInstanceSummary, type aa as WorkflowStepDetail, ab as createLocalStore, ac as createStream, ad as getErrorCode, ae as getRetryAfterMs, af as isConflictError, ag as isForbiddenError, ah as isRateLimitedError, ai as isUnauthorizedError } from "./packem_shared/lunora-client.d-Dy4neKF6.js";
3
+ export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-DI-5eqHP.js";
4
+ export type { AuthCapabilities, AuthConfigInfo, AuthImpersonation, AuthPage, AuthSession, AuthUser, AuthUserFieldSpec, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
5
5
  /**
6
6
  * The slice of React Native's `AsyncStorage` (or any async key/value store —
7
7
  * Expo `SecureStore`, a wrapped `localForage`, an in-memory map in tests) this
package/dist/index.mjs CHANGED
@@ -3,13 +3,13 @@ export { default as createInMemoryBookmarkStorage } from './packem_shared/create
3
3
  export { applyDelta, isMutationDelta } from './packem_shared/applyDelta-4jFGTPA3.mjs';
4
4
  export { CONFLICT_ERROR_CODE, getErrorCode, getRetryAfterMs, isConflictError, isForbiddenError, isRateLimitedError, isUnauthorizedError } from './packem_shared/CONFLICT_ERROR_CODE-B8gQ8tyU.mjs';
5
5
  export { c as createLocalStore } from './packem_shared/local-store-BNgN3Dw3.mjs';
6
- export { LunoraClient } from './packem_shared/LunoraClient-Zb_AVP5H.mjs';
6
+ export { LunoraClient } from './packem_shared/LunoraClient-BECgZjx4.mjs';
7
7
  export { createMutationRunner } from './packem_shared/createMutationRunner-BqsavzvG.mjs';
8
8
  export { createMutatorRunner } from './packem_shared/createMutatorRunner-BETvCd0p.mjs';
9
9
  export { O as OfflineQueue } from './packem_shared/offline-queue-B9vfdSqp.mjs';
10
- export { createInMemoryPersistence, createIndexedDbPersistence } from './packem_shared/createInMemoryPersistence-CY6F0ZvQ.mjs';
10
+ export { createInMemoryPersistence, createIndexedDbPersistence } from './packem_shared/createInMemoryPersistence-Ds7z8n8d.mjs';
11
11
  export { preloadQuery, preloadedQueryResult } from './packem_shared/preloadQuery-lobFkD2Z.mjs';
12
- export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey } from './packem_shared/createInMemoryQueryCache-Bv4Ruv6n.mjs';
12
+ export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey } from './packem_shared/createInMemoryQueryCache-iWtKPrid.mjs';
13
13
  export { createReconnect } from './packem_shared/createReconnect-Di_-oHH7.mjs';
14
14
  export { DEFAULT_MAX_BUFFER, createStream } from './packem_shared/DEFAULT_MAX_BUFFER-BDkqO5PW.mjs';
15
15
  export { S as SubscriptionRegistry } from './packem_shared/subscription-DoyO04-2.mjs';
@@ -1,10 +1,11 @@
1
+ import { LunoraError } from '@lunora/errors';
1
2
  import { S as SubscriptionRegistry, s as stableStringify } from './subscription-DoyO04-2.mjs';
2
3
  import createInMemoryBookmarkStorage from './createInMemoryBookmarkStorage-BoN7a7TH.mjs';
3
4
  import { isMutationDelta, applyDelta } from './applyDelta-4jFGTPA3.mjs';
4
5
  import { a as applyOptimisticLayer, d as dropConfirmedLayers, n as notifySubscription, f as foldOptimistic, c as createLocalStore } from './local-store-BNgN3Dw3.mjs';
5
6
  import { O as OfflineQueue, n as nextId, i as isStaleVersion, r as reportPersistenceError } from './offline-queue-B9vfdSqp.mjs';
6
- import { resolvePersistenceAdapter } from './createInMemoryPersistence-CY6F0ZvQ.mjs';
7
- import { resolveQueryCacheAdapter, queryCacheKey } from './createInMemoryQueryCache-Bv4Ruv6n.mjs';
7
+ import { resolvePersistenceAdapter } from './createInMemoryPersistence-Ds7z8n8d.mjs';
8
+ import { resolveQueryCacheAdapter, queryCacheKey } from './createInMemoryQueryCache-iWtKPrid.mjs';
8
9
  import { createReconnect } from './createReconnect-Di_-oHH7.mjs';
9
10
  import { createStream } from './DEFAULT_MAX_BUFFER-BDkqO5PW.mjs';
10
11
 
@@ -331,6 +332,24 @@ const AUTH_ORG_MEMBERS_PATH = "/_lunora/admin/auth/organizations/members";
331
332
  const AUTH_ORG_INVITATIONS_PATH = "/_lunora/admin/auth/organizations/invitations";
332
333
  const AUTH_REMOVE_MEMBER_PATH = "/_lunora/admin/auth/organizations/members/remove";
333
334
  const AUTH_CANCEL_INVITATION_PATH = "/_lunora/admin/auth/organizations/invitations/cancel";
335
+ const AUTH_CONFIG_PATH = "/_lunora/admin/auth/config";
336
+ const AUTH_CREATE_ORG_PATH = "/_lunora/admin/auth/organizations/create";
337
+ const AUTH_UPDATE_ORG_PATH = "/_lunora/admin/auth/organizations/update";
338
+ const AUTH_REMOVE_ORG_PATH = "/_lunora/admin/auth/organizations/remove";
339
+ const AUTH_ADD_MEMBER_PATH = "/_lunora/admin/auth/organizations/members/add";
340
+ const AUTH_INVITE_MEMBER_PATH = "/_lunora/admin/auth/organizations/members/invite";
341
+ const AUTH_MEMBER_ROLE_PATH = "/_lunora/admin/auth/organizations/members/role";
342
+ const AUTH_ORG_TEAMS_PATH = "/_lunora/admin/auth/organizations/teams";
343
+ const AUTH_CREATE_TEAM_PATH = "/_lunora/admin/auth/organizations/teams/create";
344
+ const AUTH_UPDATE_TEAM_PATH = "/_lunora/admin/auth/organizations/teams/update";
345
+ const AUTH_REMOVE_TEAM_PATH = "/_lunora/admin/auth/organizations/teams/remove";
346
+ const AUTH_ORG_TEAM_MEMBERS_PATH = "/_lunora/admin/auth/organizations/teams/members";
347
+ const AUTH_ADD_TEAM_MEMBER_PATH = "/_lunora/admin/auth/organizations/teams/members/add";
348
+ const AUTH_REMOVE_TEAM_MEMBER_PATH = "/_lunora/admin/auth/organizations/teams/members/remove";
349
+ const AUTH_ORG_ROLES_PATH = "/_lunora/admin/auth/organizations/roles";
350
+ const AUTH_CREATE_ROLE_PATH = "/_lunora/admin/auth/organizations/roles/create";
351
+ const AUTH_UPDATE_ROLE_PATH = "/_lunora/admin/auth/organizations/roles/update";
352
+ const AUTH_REMOVE_ROLE_PATH = "/_lunora/admin/auth/organizations/roles/remove";
334
353
  const DEFAULT_AUTH_BASE_PATH = "/api/auth";
335
354
  const GET_SESSION_PATH = "/get-session";
336
355
  const deriveWsUrl = (url) => {
@@ -406,6 +425,12 @@ const reconstructError = (errorBody) => {
406
425
  if (errorBody.data !== void 0) {
407
426
  error.data = decodeWire(errorBody.data);
408
427
  }
428
+ if (errorBody.hint !== void 0) {
429
+ error.hint = errorBody.hint;
430
+ }
431
+ if (errorBody.docsUrl !== void 0) {
432
+ error.docsUrl = errorBody.docsUrl;
433
+ }
409
434
  return error;
410
435
  };
411
436
  const encodeCallArgs = (payload, label) => {
@@ -692,7 +717,7 @@ class LunoraClient {
692
717
  async callMutator(functionPath, args, options) {
693
718
  const clientSeq = options?.clientSeq;
694
719
  if (clientSeq !== void 0 && (!Number.isInteger(clientSeq) || clientSeq <= 0)) {
695
- throw new Error(`callMutator: clientSeq must be a positive integer, got ${String(clientSeq)}`);
720
+ throw new LunoraError("INTERNAL", `callMutator: clientSeq must be a positive integer, got ${String(clientSeq)}`);
696
721
  }
697
722
  const bucket = options?.shardKey ?? "";
698
723
  let ackWatermark;
@@ -976,7 +1001,7 @@ class LunoraClient {
976
1001
  // --- RPC ---------------------------------------------------------------
977
1002
  async query(function_, args, options = {}) {
978
1003
  if (this.closed) {
979
- throw new Error("LunoraClient is closed");
1004
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
980
1005
  }
981
1006
  return await this.rpc(function_.__lunoraRef, args, options.shardKey, { attachBookmark: true });
982
1007
  }
@@ -996,10 +1021,10 @@ class LunoraClient {
996
1021
  */
997
1022
  async batch(calls) {
998
1023
  if (this.closed) {
999
- throw new Error("LunoraClient is closed");
1024
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1000
1025
  }
1001
1026
  if (!this.fetchImpl) {
1002
- throw new Error("LunoraClient: no `fetch` implementation available");
1027
+ throw new LunoraError("INTERNAL", "LunoraClient: no `fetch` implementation available");
1003
1028
  }
1004
1029
  if (calls.length === 0) {
1005
1030
  return [];
@@ -1026,13 +1051,13 @@ class LunoraClient {
1026
1051
  try {
1027
1052
  body = await response.json();
1028
1053
  } catch {
1029
- throw new Error(`LunoraClient: batch response was not JSON (status ${response.status.toString()})`);
1054
+ throw new LunoraError("INTERNAL", `LunoraClient: batch response was not JSON (status ${response.status.toString()})`);
1030
1055
  }
1031
1056
  if (!response.ok || body.error && !body.results) {
1032
1057
  if (body.error) {
1033
1058
  throw reconstructError(body.error);
1034
1059
  }
1035
- throw new Error(`LunoraClient: batch request failed (status ${response.status.toString()})`);
1060
+ throw new LunoraError("INTERNAL", `LunoraClient: batch request failed (status ${response.status.toString()})`);
1036
1061
  }
1037
1062
  return demuxBatchResults(body.results ?? [], calls.length);
1038
1063
  }
@@ -1048,7 +1073,7 @@ class LunoraClient {
1048
1073
  */
1049
1074
  async mutation(function_, args, options = {}) {
1050
1075
  if (this.closed) {
1051
- throw new Error("LunoraClient is closed");
1076
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1052
1077
  }
1053
1078
  const argsRecord = args;
1054
1079
  const mutationId = options.mutationId ?? nextId();
@@ -1092,7 +1117,7 @@ class LunoraClient {
1092
1117
  }
1093
1118
  async action(function_, args, options = {}) {
1094
1119
  if (this.closed) {
1095
- throw new Error("LunoraClient is closed");
1120
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1096
1121
  }
1097
1122
  return await this.rpc(function_.__lunoraRef, args, options.shardKey);
1098
1123
  }
@@ -1109,7 +1134,7 @@ class LunoraClient {
1109
1134
  */
1110
1135
  async shardTraffic(table) {
1111
1136
  if (this.closed) {
1112
- throw new Error("LunoraClient is closed");
1137
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1113
1138
  }
1114
1139
  const body = await this.adminFetch(SHARD_TRAFFIC_PATH, "POST", { table });
1115
1140
  return { failed: body.failed ?? 0, ok: body.ok ?? 0, shards: body.shards ?? [] };
@@ -1124,7 +1149,7 @@ class LunoraClient {
1124
1149
  */
1125
1150
  async listScheduledJobs() {
1126
1151
  if (this.closed) {
1127
- throw new Error("LunoraClient is closed");
1152
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1128
1153
  }
1129
1154
  const body = await this.adminFetch(SCHEDULED_PATH, "GET");
1130
1155
  return body.records ?? [];
@@ -1140,7 +1165,7 @@ class LunoraClient {
1140
1165
  */
1141
1166
  async schedulerStatus() {
1142
1167
  if (this.closed) {
1143
- throw new Error("LunoraClient is closed");
1168
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1144
1169
  }
1145
1170
  const body = await this.adminFetch(SCHEDULED_STATUS_PATH, "GET");
1146
1171
  return {
@@ -1152,7 +1177,7 @@ class LunoraClient {
1152
1177
  /** Cancel a pending scheduled job by id. Returns whether a job was removed. */
1153
1178
  async cancelScheduledJob(id) {
1154
1179
  if (this.closed) {
1155
- throw new Error("LunoraClient is closed");
1180
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1156
1181
  }
1157
1182
  const body = await this.adminFetch(SCHEDULED_CANCEL_PATH, "POST", { id });
1158
1183
  return { cancelled: body.cancelled === true };
@@ -1167,7 +1192,7 @@ class LunoraClient {
1167
1192
  */
1168
1193
  async listDeadJobs() {
1169
1194
  if (this.closed) {
1170
- throw new Error("LunoraClient is closed");
1195
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1171
1196
  }
1172
1197
  const body = await this.adminFetch(SCHEDULED_DEAD_PATH, "GET");
1173
1198
  return body.records ?? [];
@@ -1179,7 +1204,7 @@ class LunoraClient {
1179
1204
  */
1180
1205
  async retryDeadJob(id) {
1181
1206
  if (this.closed) {
1182
- throw new Error("LunoraClient is closed");
1207
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1183
1208
  }
1184
1209
  const body = await this.adminFetch(SCHEDULED_DEAD_RETRY_PATH, "POST", { id });
1185
1210
  return { retried: body.retried === true };
@@ -1191,7 +1216,7 @@ class LunoraClient {
1191
1216
  */
1192
1217
  async removeDeadJob(id) {
1193
1218
  if (this.closed) {
1194
- throw new Error("LunoraClient is closed");
1219
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1195
1220
  }
1196
1221
  const body = await this.adminFetch(SCHEDULED_DEAD_CANCEL_PATH, "POST", { id });
1197
1222
  return { removed: body.removed === true };
@@ -1209,7 +1234,7 @@ class LunoraClient {
1209
1234
  */
1210
1235
  async listWorkflowInstances(options) {
1211
1236
  if (this.closed) {
1212
- throw new Error("LunoraClient is closed");
1237
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1213
1238
  }
1214
1239
  const query = new URLSearchParams({ name: options.name });
1215
1240
  if (options.status !== void 0) {
@@ -1233,7 +1258,7 @@ class LunoraClient {
1233
1258
  /** Read one workflow instance with its step timeline (`/_lunora/admin/workflows/instance`). */
1234
1259
  async getWorkflowInstance(options) {
1235
1260
  if (this.closed) {
1236
- throw new Error("LunoraClient is closed");
1261
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1237
1262
  }
1238
1263
  const query = new URLSearchParams({ id: options.id, name: options.name });
1239
1264
  const body = await this.adminFetch(`${WORKFLOWS_INSTANCE_PATH}?${query.toString()}`, "GET");
@@ -1252,7 +1277,7 @@ class LunoraClient {
1252
1277
  /** Pause / resume / terminate a workflow instance (`/_lunora/admin/workflows/status`). Needs an Edit-scoped Cloudflare token. */
1253
1278
  async setWorkflowInstanceStatus(options) {
1254
1279
  if (this.closed) {
1255
- throw new Error("LunoraClient is closed");
1280
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1256
1281
  }
1257
1282
  const body = await this.adminFetch(WORKFLOWS_STATUS_PATH, "POST", { action: options.action, id: options.id, name: options.name });
1258
1283
  return { status: body.status ?? "unknown" };
@@ -1267,7 +1292,7 @@ class LunoraClient {
1267
1292
  */
1268
1293
  subscribeScheduledJobs(onJobs) {
1269
1294
  if (this.closed) {
1270
- throw new Error("LunoraClient is closed");
1295
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1271
1296
  }
1272
1297
  if (this.WebSocketImpl === void 0) {
1273
1298
  return () => void 0;
@@ -1323,7 +1348,7 @@ class LunoraClient {
1323
1348
  */
1324
1349
  async listFunctions() {
1325
1350
  if (this.closed) {
1326
- throw new Error("LunoraClient is closed");
1351
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1327
1352
  }
1328
1353
  const body = await this.adminFetch(FUNCTIONS_PATH, "GET");
1329
1354
  return body.functions ?? [];
@@ -1339,7 +1364,7 @@ class LunoraClient {
1339
1364
  */
1340
1365
  async getCronJobs() {
1341
1366
  if (this.closed) {
1342
- throw new Error("LunoraClient is closed");
1367
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1343
1368
  }
1344
1369
  const body = await this.adminFetch(CRON_JOBS_PATH, "GET");
1345
1370
  return body.jobs ?? [];
@@ -1355,7 +1380,7 @@ class LunoraClient {
1355
1380
  */
1356
1381
  async runCronJob(name) {
1357
1382
  if (this.closed) {
1358
- throw new Error("LunoraClient is closed");
1383
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1359
1384
  }
1360
1385
  const body = await this.adminFetch(CRON_JOBS_RUN_PATH, "POST", { name });
1361
1386
  return { name: body.name ?? name, ran: body.ran === true };
@@ -1370,7 +1395,7 @@ class LunoraClient {
1370
1395
  */
1371
1396
  async fetchOpenApi() {
1372
1397
  if (this.closed) {
1373
- throw new Error("LunoraClient is closed");
1398
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1374
1399
  }
1375
1400
  return await this.adminFetch(OPENAPI_PATH, "GET");
1376
1401
  }
@@ -1386,7 +1411,7 @@ class LunoraClient {
1386
1411
  */
1387
1412
  async fetchOpenRpc() {
1388
1413
  if (this.closed) {
1389
- throw new Error("LunoraClient is closed");
1414
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1390
1415
  }
1391
1416
  return await this.adminFetch(OPENRPC_PATH, "GET");
1392
1417
  }
@@ -1400,7 +1425,7 @@ class LunoraClient {
1400
1425
  */
1401
1426
  async listStorageObjects(options = {}) {
1402
1427
  if (this.closed) {
1403
- throw new Error("LunoraClient is closed");
1428
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1404
1429
  }
1405
1430
  const params = new URLSearchParams();
1406
1431
  if (options.prefix !== void 0 && options.prefix !== "") {
@@ -1428,7 +1453,7 @@ class LunoraClient {
1428
1453
  */
1429
1454
  async deleteStorageObject(key, options) {
1430
1455
  if (this.closed) {
1431
- throw new Error("LunoraClient is closed");
1456
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1432
1457
  }
1433
1458
  const path = `${STORAGE_PATH}?key=${encodeURIComponent(key)}${bucketQuery(options?.bucket)}`;
1434
1459
  const body = await this.adminFetch(path, "DELETE");
@@ -1442,7 +1467,7 @@ class LunoraClient {
1442
1467
  */
1443
1468
  async listStorageBuckets() {
1444
1469
  if (this.closed) {
1445
- throw new Error("LunoraClient is closed");
1470
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1446
1471
  }
1447
1472
  const body = await this.adminFetch(STORAGE_BUCKETS_PATH, "GET");
1448
1473
  return body.buckets ?? [];
@@ -1456,7 +1481,7 @@ class LunoraClient {
1456
1481
  */
1457
1482
  async uploadStorageObject(options) {
1458
1483
  if (this.closed) {
1459
- throw new Error("LunoraClient is closed");
1484
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1460
1485
  }
1461
1486
  const path = `${STORAGE_PATH}?key=${encodeURIComponent(options.key)}${bucketQuery(options.bucket)}`;
1462
1487
  const body = await this.adminFetch(path, "PUT", options.body, options.contentType);
@@ -1475,7 +1500,7 @@ class LunoraClient {
1475
1500
  */
1476
1501
  async signedStorageUrl(key, options) {
1477
1502
  if (this.closed) {
1478
- throw new Error("LunoraClient is closed");
1503
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1479
1504
  }
1480
1505
  const expiresInSeconds = options?.expiresInSeconds;
1481
1506
  const expiryQuery = expiresInSeconds === void 0 ? "" : `&expiresIn=${encodeURIComponent(expiresInSeconds.toString())}`;
@@ -1495,7 +1520,7 @@ class LunoraClient {
1495
1520
  */
1496
1521
  async listGlobalTables() {
1497
1522
  if (this.closed) {
1498
- throw new Error("LunoraClient is closed");
1523
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1499
1524
  }
1500
1525
  return await this.adminFetch(GLOBAL_TABLES_PATH, "GET");
1501
1526
  }
@@ -1507,7 +1532,7 @@ class LunoraClient {
1507
1532
  */
1508
1533
  async readGlobalTablePage(options) {
1509
1534
  if (this.closed) {
1510
- throw new Error("LunoraClient is closed");
1535
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1511
1536
  }
1512
1537
  const params = new URLSearchParams({ table: options.table });
1513
1538
  if (options.limit !== void 0) {
@@ -1530,7 +1555,7 @@ class LunoraClient {
1530
1555
  */
1531
1556
  async facetGlobalColumn(options) {
1532
1557
  if (this.closed) {
1533
- throw new Error("LunoraClient is closed");
1558
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1534
1559
  }
1535
1560
  const params = new URLSearchParams({ column: options.column, table: options.table });
1536
1561
  if (options.limit !== void 0) {
@@ -1553,7 +1578,7 @@ class LunoraClient {
1553
1578
  */
1554
1579
  async listVectorIndexes() {
1555
1580
  if (this.closed) {
1556
- throw new Error("LunoraClient is closed");
1581
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1557
1582
  }
1558
1583
  const body = await this.adminFetch(VECTOR_INDEXES_PATH, "GET");
1559
1584
  return body.indexes ?? [];
@@ -1567,7 +1592,7 @@ class LunoraClient {
1567
1592
  */
1568
1593
  async queryVectorIndex(options) {
1569
1594
  if (this.closed) {
1570
- throw new Error("LunoraClient is closed");
1595
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1571
1596
  }
1572
1597
  const body = await this.adminFetch(VECTOR_QUERY_PATH, "POST", options);
1573
1598
  return body.matches ?? [];
@@ -1581,7 +1606,7 @@ class LunoraClient {
1581
1606
  */
1582
1607
  async listKvNamespaces() {
1583
1608
  if (this.closed) {
1584
- throw new Error("LunoraClient is closed");
1609
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1585
1610
  }
1586
1611
  const body = await this.adminFetch(KV_NAMESPACES_PATH, "GET");
1587
1612
  return body.namespaces ?? [];
@@ -1593,7 +1618,7 @@ class LunoraClient {
1593
1618
  */
1594
1619
  async listKvKeys(options) {
1595
1620
  if (this.closed) {
1596
- throw new Error("LunoraClient is closed");
1621
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1597
1622
  }
1598
1623
  const path = withQuery(KV_KEYS_PATH, {
1599
1624
  cursor: options.cursor,
@@ -1610,7 +1635,7 @@ class LunoraClient {
1610
1635
  */
1611
1636
  async getKvValue(options) {
1612
1637
  if (this.closed) {
1613
- throw new Error("LunoraClient is closed");
1638
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1614
1639
  }
1615
1640
  const path = withQuery(KV_VALUE_PATH, { key: options.key, namespace: options.namespace });
1616
1641
  return await this.adminFetch(path, "GET");
@@ -1623,7 +1648,7 @@ class LunoraClient {
1623
1648
  */
1624
1649
  async putKvValue(options) {
1625
1650
  if (this.closed) {
1626
- throw new Error("LunoraClient is closed");
1651
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1627
1652
  }
1628
1653
  await this.adminFetch(KV_VALUE_PATH, "PUT", options);
1629
1654
  }
@@ -1633,7 +1658,7 @@ class LunoraClient {
1633
1658
  */
1634
1659
  async deleteKvKey(options) {
1635
1660
  if (this.closed) {
1636
- throw new Error("LunoraClient is closed");
1661
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1637
1662
  }
1638
1663
  const path = withQuery(KV_VALUE_PATH, { key: options.key, namespace: options.namespace });
1639
1664
  await this.adminFetch(path, "DELETE");
@@ -1647,7 +1672,7 @@ class LunoraClient {
1647
1672
  */
1648
1673
  async listAuthUsers(options = {}) {
1649
1674
  if (this.closed) {
1650
- throw new Error("LunoraClient is closed");
1675
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1651
1676
  }
1652
1677
  const path = withQuery(AUTH_USERS_PATH, {
1653
1678
  filterField: options.filterField,
@@ -1759,10 +1784,90 @@ class LunoraClient {
1759
1784
  async cancelAuthOrgInvitation(input) {
1760
1785
  await this.adminFetch(AUTH_CANCEL_INVITATION_PATH, "POST", input);
1761
1786
  }
1787
+ /**
1788
+ * Report the deployment's auth configuration — enabled plugins, sign-in
1789
+ * methods, user-settable create-user fields, organization sub-features
1790
+ * (teams / roles), and session / rate-limit policy. Drives the config panel
1791
+ * and the dynamic create-user form. Never carries a secret.
1792
+ */
1793
+ async getAuthConfig() {
1794
+ return await this.adminFetch(AUTH_CONFIG_PATH, "GET");
1795
+ }
1796
+ /** Create an organization; optionally seed an `owner` member for `ownerId`. */
1797
+ async createAuthOrganization(input) {
1798
+ return await this.adminFetch(AUTH_CREATE_ORG_PATH, "POST", input);
1799
+ }
1800
+ /** Update an organization's name/slug/logo/metadata. */
1801
+ async updateAuthOrganization(input) {
1802
+ return await this.adminFetch(AUTH_UPDATE_ORG_PATH, "POST", input);
1803
+ }
1804
+ /** Delete an organization and cascade its members, invitations, teams, and custom roles. */
1805
+ async deleteAuthOrganization(input) {
1806
+ await this.adminFetch(AUTH_REMOVE_ORG_PATH, "POST", input);
1807
+ }
1808
+ /** Directly add an existing user to an organization (no invitation/acceptance). */
1809
+ async addAuthOrgMember(input) {
1810
+ return await this.adminFetch(AUTH_ADD_MEMBER_PATH, "POST", input);
1811
+ }
1812
+ /** Create a pending email invitation to an organization. */
1813
+ async inviteAuthOrgMember(input) {
1814
+ return await this.adminFetch(AUTH_INVITE_MEMBER_PATH, "POST", input);
1815
+ }
1816
+ /** Change a member's role. */
1817
+ async setAuthOrgMemberRole(input) {
1818
+ return await this.adminFetch(AUTH_MEMBER_ROLE_PATH, "POST", input);
1819
+ }
1820
+ /** List an organization's teams (requires the organization plugin with teams enabled). */
1821
+ async listAuthOrgTeams(input) {
1822
+ const path = withQuery(AUTH_ORG_TEAMS_PATH, { limit: input.limit, offset: input.offset, organizationId: input.organizationId });
1823
+ return await this.adminFetch(path, "GET");
1824
+ }
1825
+ /** Create a team under an organization. */
1826
+ async createAuthOrgTeam(input) {
1827
+ return await this.adminFetch(AUTH_CREATE_TEAM_PATH, "POST", input);
1828
+ }
1829
+ /** Rename a team. */
1830
+ async updateAuthOrgTeam(input) {
1831
+ return await this.adminFetch(AUTH_UPDATE_TEAM_PATH, "POST", input);
1832
+ }
1833
+ /** Delete a team and its memberships. */
1834
+ async removeAuthOrgTeam(input) {
1835
+ await this.adminFetch(AUTH_REMOVE_TEAM_PATH, "POST", input);
1836
+ }
1837
+ /** List a team's members. */
1838
+ async listAuthOrgTeamMembers(input) {
1839
+ const path = withQuery(AUTH_ORG_TEAM_MEMBERS_PATH, { limit: input.limit, offset: input.offset, teamId: input.teamId });
1840
+ return await this.adminFetch(path, "GET");
1841
+ }
1842
+ /** Add a user to a team. */
1843
+ async addAuthOrgTeamMember(input) {
1844
+ return await this.adminFetch(AUTH_ADD_TEAM_MEMBER_PATH, "POST", input);
1845
+ }
1846
+ /** Remove a member from a team. */
1847
+ async removeAuthOrgTeamMember(input) {
1848
+ await this.adminFetch(AUTH_REMOVE_TEAM_MEMBER_PATH, "POST", input);
1849
+ }
1850
+ /** List an organization's custom roles (requires the organization plugin with dynamic access control). */
1851
+ async listAuthOrgRoles(input) {
1852
+ const path = withQuery(AUTH_ORG_ROLES_PATH, { limit: input.limit, offset: input.offset, organizationId: input.organizationId });
1853
+ return await this.adminFetch(path, "GET");
1854
+ }
1855
+ /** Create a custom org role with a permission grant (a `resource -> actions[]` map). */
1856
+ async createAuthOrgRole(input) {
1857
+ return await this.adminFetch(AUTH_CREATE_ROLE_PATH, "POST", input);
1858
+ }
1859
+ /** Replace a custom org role's permission grant. */
1860
+ async updateAuthOrgRole(input) {
1861
+ return await this.adminFetch(AUTH_UPDATE_ROLE_PATH, "POST", input);
1862
+ }
1863
+ /** Delete a custom org role. */
1864
+ async deleteAuthOrgRole(input) {
1865
+ await this.adminFetch(AUTH_REMOVE_ROLE_PATH, "POST", input);
1866
+ }
1762
1867
  /** List auth sessions, paged and optionally filtered to one user. */
1763
1868
  async listAuthSessions(options = {}) {
1764
1869
  if (this.closed) {
1765
- throw new Error("LunoraClient is closed");
1870
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1766
1871
  }
1767
1872
  const params = new URLSearchParams();
1768
1873
  if (options.userId !== void 0 && options.userId !== "") {
@@ -1780,7 +1885,7 @@ class LunoraClient {
1780
1885
  // --- Subscriptions ------------------------------------------------------
1781
1886
  subscribe(function_, args, callback, options = {}) {
1782
1887
  if (this.closed) {
1783
- throw new Error("LunoraClient is closed");
1888
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1784
1889
  }
1785
1890
  const argsRecord = args ?? {};
1786
1891
  const key = SubscriptionRegistry.key(function_.__lunoraRef, argsRecord, options.shardKey);
@@ -1858,7 +1963,7 @@ class LunoraClient {
1858
1963
  */
1859
1964
  subscribeShape(shape, callback, options = {}) {
1860
1965
  if (this.closed) {
1861
- throw new Error("LunoraClient is closed");
1966
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1862
1967
  }
1863
1968
  this.nextShapeId += 1;
1864
1969
  const id = `shape_${this.nextShapeId.toString()}`;
@@ -1904,10 +2009,10 @@ class LunoraClient {
1904
2009
  */
1905
2010
  stream(function_, args, options = {}) {
1906
2011
  if (this.closed) {
1907
- throw new Error("LunoraClient is closed");
2012
+ throw new LunoraError("INTERNAL", "LunoraClient is closed");
1908
2013
  }
1909
2014
  if (this.WebSocketImpl === void 0) {
1910
- throw new Error("LunoraClient: streams require a WebSocket implementation");
2015
+ throw new LunoraError("INTERNAL", "LunoraClient: streams require a WebSocket implementation");
1911
2016
  }
1912
2017
  this.nextStreamId += 1;
1913
2018
  const id = `stream_${this.nextStreamId.toString()}`;
@@ -2357,7 +2462,7 @@ class LunoraClient {
2357
2462
  }
2358
2463
  async rpc(functionPath, args, shardKey, flags = {}) {
2359
2464
  if (!this.fetchImpl) {
2360
- throw new Error("LunoraClient: no `fetch` implementation available");
2465
+ throw new LunoraError("INTERNAL", "LunoraClient: no `fetch` implementation available");
2361
2466
  }
2362
2467
  const headers = this.rpcRequestHeaders(flags);
2363
2468
  const response = await this.fetchImpl(joinUrl(this.url, RPC_PATH), {
@@ -2379,14 +2484,14 @@ class LunoraClient {
2379
2484
  body = await response.json();
2380
2485
  } catch {
2381
2486
  const statusText = response.statusText ? ` ${response.statusText}` : "";
2382
- throw new Error(`LunoraClient: response was not JSON (status ${response.status.toString()}${statusText})`);
2487
+ throw new LunoraError("INTERNAL", `LunoraClient: response was not JSON (status ${response.status.toString()}${statusText})`);
2383
2488
  }
2384
2489
  if ("error" in body) {
2385
2490
  throw reconstructError(body.error);
2386
2491
  }
2387
2492
  if (!response.ok) {
2388
2493
  const statusText = response.statusText ? ` ${response.statusText}` : "";
2389
- throw new Error(`LunoraClient: request failed (status ${response.status.toString()}${statusText})`);
2494
+ throw new LunoraError("INTERNAL", `LunoraClient: request failed (status ${response.status.toString()}${statusText})`);
2390
2495
  }
2391
2496
  flags.onMutationAck?.(body.lastMutationId);
2392
2497
  flags.onCommitCursor?.(body.commitCursor);
@@ -2400,7 +2505,7 @@ class LunoraClient {
2400
2505
  */
2401
2506
  async adminFetch(path, method, payload, contentType) {
2402
2507
  if (!this.fetchImpl) {
2403
- throw new Error("LunoraClient: no `fetch` implementation available");
2508
+ throw new LunoraError("INTERNAL", "LunoraClient: no `fetch` implementation available");
2404
2509
  }
2405
2510
  const headers = {};
2406
2511
  if (this.authToken) {
@@ -2429,7 +2534,7 @@ class LunoraClient {
2429
2534
  body = await response.json();
2430
2535
  } catch {
2431
2536
  const statusText = response.statusText ? ` ${response.statusText}` : "";
2432
- throw new Error(`LunoraClient: response was not JSON (status ${response.status.toString()}${statusText})`);
2537
+ throw new LunoraError("INTERNAL", `LunoraClient: response was not JSON (status ${response.status.toString()}${statusText})`);
2433
2538
  }
2434
2539
  if (typeof body === "object" && body !== null && "error" in body) {
2435
2540
  const envelope = body.error;
@@ -2439,7 +2544,7 @@ class LunoraClient {
2439
2544
  }
2440
2545
  if (!response.ok) {
2441
2546
  const statusText = response.statusText ? ` ${response.statusText}` : "";
2442
- throw new Error(`LunoraClient: admin request failed (status ${response.status.toString()}${statusText})`);
2547
+ throw new LunoraError("INTERNAL", `LunoraClient: admin request failed (status ${response.status.toString()}${statusText})`);
2443
2548
  }
2444
2549
  return body;
2445
2550
  }
@@ -1,3 +1,5 @@
1
+ import { LunoraError } from '@lunora/errors';
2
+
1
3
  const createInMemoryPersistence = () => {
2
4
  const entries = /* @__PURE__ */ new Map();
3
5
  const clone = (mutation) => {
@@ -39,7 +41,7 @@ const promisifyRequest = (request) => new Promise((resolve, reject) => {
39
41
  const createIndexedDbPersistence = (options = {}) => {
40
42
  const factory = options.indexedDB ?? (typeof indexedDB === "undefined" ? void 0 : indexedDB);
41
43
  if (!factory) {
42
- throw new Error("createIndexedDbPersistence: no IndexedDB available — pass `indexedDB` or use createInMemoryPersistence()");
44
+ throw new LunoraError("INTERNAL", "createIndexedDbPersistence: no IndexedDB available — pass `indexedDB` or use createInMemoryPersistence()");
43
45
  }
44
46
  const databaseName = options.databaseName ?? DEFAULT_DATABASE;
45
47
  const storeName = options.storeName ?? DEFAULT_STORE;
@@ -1,3 +1,5 @@
1
+ import { LunoraError } from '@lunora/errors';
2
+
1
3
  const queryCacheKey = (functionPath, argsKey, shardKey) => `${functionPath}::${argsKey}::${shardKey ?? ""}`;
2
4
  const DEFAULT_MAX_ENTRIES = 500;
3
5
  const createInMemoryQueryCache = (options = {}) => {
@@ -50,7 +52,7 @@ const promisifyRequest = (request) => new Promise((resolve, reject) => {
50
52
  const createIndexedDbQueryCache = (options = {}) => {
51
53
  const factory = options.indexedDB ?? (typeof indexedDB === "undefined" ? void 0 : indexedDB);
52
54
  if (!factory) {
53
- throw new Error("createIndexedDbQueryCache: no IndexedDB available — pass `indexedDB` or use createInMemoryQueryCache()");
55
+ throw new LunoraError("INTERNAL", "createIndexedDbQueryCache: no IndexedDB available — pass `indexedDB` or use createInMemoryQueryCache()");
54
56
  }
55
57
  const databaseName = options.databaseName ?? DEFAULT_DATABASE;
56
58
  const storeName = options.storeName ?? DEFAULT_STORE;
@@ -1,4 +1,4 @@
1
- import { LunoraClient } from './LunoraClient-Zb_AVP5H.mjs';
1
+ import { LunoraClient } from './LunoraClient-BECgZjx4.mjs';
2
2
 
3
3
  const createServerClient = (options) => {
4
4
  const client = new LunoraClient({ fetch: options.fetch, url: options.url });
@@ -1,4 +1,4 @@
1
- import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthSession } from '@lunora/runtime';
1
+ import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthConfigInfo, AuthSession } from '@lunora/runtime';
2
2
  /**
3
3
  * The machine-readable error codes a client can observe on a failed
4
4
  * RPC/batch/subscription. Mirrors the server's `CODE_STATUS` keys
@@ -1207,10 +1207,20 @@ interface SyncWatermark {
1207
1207
  checkpoint?: number;
1208
1208
  mutationId?: number;
1209
1209
  }
1210
- /** An `Error` carrying the server's machine-readable `code` and (for a `LunoraError`) structured `data`. The client's public error contract for RPC/batch failures. The `(string & {})` arm keeps forward-compat/unknown server codes assignable without losing autocomplete on the known {@link LunoraErrorCode} union. */
1210
+ /**
1211
+ * An `Error` carrying the server's machine-readable `code` and (for a
1212
+ * `LunoraError`) structured `data`, plus an optional actionable `hint` (Markdown)
1213
+ * and `docsUrl` resolved from the central error catalog. The client's public
1214
+ * error contract for RPC/batch failures — a UI can render `hint`/`docsUrl` to
1215
+ * tell the user how to fix the error. The `(string & {})` arm keeps
1216
+ * forward-compat/unknown server codes assignable without losing autocomplete on
1217
+ * the known {@link LunoraErrorCode} union.
1218
+ */
1211
1219
  type LunoraClientError = Error & {
1212
1220
  code?: LunoraErrorCode | (string & {});
1213
1221
  data?: unknown;
1222
+ docsUrl?: string;
1223
+ hint?: string | string[];
1214
1224
  };
1215
1225
  /** One demuxed result slot of a {@link LunoraClient.batch} call (plan 088). */
1216
1226
  type BatchSlot = {
@@ -2038,6 +2048,107 @@ declare class LunoraClient {
2038
2048
  cancelAuthOrgInvitation(input: {
2039
2049
  invitationId: string;
2040
2050
  }): Promise<void>;
2051
+ /**
2052
+ * Report the deployment's auth configuration — enabled plugins, sign-in
2053
+ * methods, user-settable create-user fields, organization sub-features
2054
+ * (teams / roles), and session / rate-limit policy. Drives the config panel
2055
+ * and the dynamic create-user form. Never carries a secret.
2056
+ */
2057
+ getAuthConfig(): Promise<AuthConfigInfo>;
2058
+ /** Create an organization; optionally seed an `owner` member for `ownerId`. */
2059
+ createAuthOrganization(input: {
2060
+ logo?: string;
2061
+ metadata?: Record<string, unknown>;
2062
+ name: string;
2063
+ ownerId?: string;
2064
+ slug?: string;
2065
+ }): Promise<Record<string, unknown>>;
2066
+ /** Update an organization's name/slug/logo/metadata. */
2067
+ updateAuthOrganization(input: {
2068
+ logo?: string;
2069
+ metadata?: Record<string, unknown>;
2070
+ name?: string;
2071
+ organizationId: string;
2072
+ slug?: string;
2073
+ }): Promise<Record<string, unknown>>;
2074
+ /** Delete an organization and cascade its members, invitations, teams, and custom roles. */
2075
+ deleteAuthOrganization(input: {
2076
+ organizationId: string;
2077
+ }): Promise<void>;
2078
+ /** Directly add an existing user to an organization (no invitation/acceptance). */
2079
+ addAuthOrgMember(input: {
2080
+ organizationId: string;
2081
+ role?: string;
2082
+ userId: string;
2083
+ }): Promise<Record<string, unknown>>;
2084
+ /** Create a pending email invitation to an organization. */
2085
+ inviteAuthOrgMember(input: {
2086
+ email: string;
2087
+ inviterId?: string;
2088
+ organizationId: string;
2089
+ role?: string;
2090
+ }): Promise<Record<string, unknown>>;
2091
+ /** Change a member's role. */
2092
+ setAuthOrgMemberRole(input: {
2093
+ memberId: string;
2094
+ role: string | string[];
2095
+ }): Promise<Record<string, unknown>>;
2096
+ /** List an organization's teams (requires the organization plugin with teams enabled). */
2097
+ listAuthOrgTeams(input: {
2098
+ limit?: number;
2099
+ offset?: number;
2100
+ organizationId: string;
2101
+ }): Promise<AuthPage<Record<string, unknown>>>;
2102
+ /** Create a team under an organization. */
2103
+ createAuthOrgTeam(input: {
2104
+ name: string;
2105
+ organizationId: string;
2106
+ }): Promise<Record<string, unknown>>;
2107
+ /** Rename a team. */
2108
+ updateAuthOrgTeam(input: {
2109
+ name: string;
2110
+ teamId: string;
2111
+ }): Promise<Record<string, unknown>>;
2112
+ /** Delete a team and its memberships. */
2113
+ removeAuthOrgTeam(input: {
2114
+ teamId: string;
2115
+ }): Promise<void>;
2116
+ /** List a team's members. */
2117
+ listAuthOrgTeamMembers(input: {
2118
+ limit?: number;
2119
+ offset?: number;
2120
+ teamId: string;
2121
+ }): Promise<AuthPage<Record<string, unknown>>>;
2122
+ /** Add a user to a team. */
2123
+ addAuthOrgTeamMember(input: {
2124
+ teamId: string;
2125
+ userId: string;
2126
+ }): Promise<Record<string, unknown>>;
2127
+ /** Remove a member from a team. */
2128
+ removeAuthOrgTeamMember(input: {
2129
+ teamMemberId: string;
2130
+ }): Promise<void>;
2131
+ /** List an organization's custom roles (requires the organization plugin with dynamic access control). */
2132
+ listAuthOrgRoles(input: {
2133
+ limit?: number;
2134
+ offset?: number;
2135
+ organizationId: string;
2136
+ }): Promise<AuthPage<Record<string, unknown>>>;
2137
+ /** Create a custom org role with a permission grant (a `resource -> actions[]` map). */
2138
+ createAuthOrgRole(input: {
2139
+ organizationId: string;
2140
+ permission: Record<string, string[]>;
2141
+ role: string;
2142
+ }): Promise<Record<string, unknown>>;
2143
+ /** Replace a custom org role's permission grant. */
2144
+ updateAuthOrgRole(input: {
2145
+ permission: Record<string, string[]>;
2146
+ roleId: string;
2147
+ }): Promise<Record<string, unknown>>;
2148
+ /** Delete a custom org role. */
2149
+ deleteAuthOrgRole(input: {
2150
+ roleId: string;
2151
+ }): Promise<void>;
2041
2152
  /** List auth sessions, paged and optionally filtered to one user. */
2042
2153
  listAuthSessions(options?: {
2043
2154
  limit?: number;
@@ -1,4 +1,4 @@
1
- import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthSession } from '@lunora/runtime';
1
+ import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthConfigInfo, AuthSession } from '@lunora/runtime';
2
2
  /**
3
3
  * The machine-readable error codes a client can observe on a failed
4
4
  * RPC/batch/subscription. Mirrors the server's `CODE_STATUS` keys
@@ -1207,10 +1207,20 @@ interface SyncWatermark {
1207
1207
  checkpoint?: number;
1208
1208
  mutationId?: number;
1209
1209
  }
1210
- /** An `Error` carrying the server's machine-readable `code` and (for a `LunoraError`) structured `data`. The client's public error contract for RPC/batch failures. The `(string & {})` arm keeps forward-compat/unknown server codes assignable without losing autocomplete on the known {@link LunoraErrorCode} union. */
1210
+ /**
1211
+ * An `Error` carrying the server's machine-readable `code` and (for a
1212
+ * `LunoraError`) structured `data`, plus an optional actionable `hint` (Markdown)
1213
+ * and `docsUrl` resolved from the central error catalog. The client's public
1214
+ * error contract for RPC/batch failures — a UI can render `hint`/`docsUrl` to
1215
+ * tell the user how to fix the error. The `(string & {})` arm keeps
1216
+ * forward-compat/unknown server codes assignable without losing autocomplete on
1217
+ * the known {@link LunoraErrorCode} union.
1218
+ */
1211
1219
  type LunoraClientError = Error & {
1212
1220
  code?: LunoraErrorCode | (string & {});
1213
1221
  data?: unknown;
1222
+ docsUrl?: string;
1223
+ hint?: string | string[];
1214
1224
  };
1215
1225
  /** One demuxed result slot of a {@link LunoraClient.batch} call (plan 088). */
1216
1226
  type BatchSlot = {
@@ -2038,6 +2048,107 @@ declare class LunoraClient {
2038
2048
  cancelAuthOrgInvitation(input: {
2039
2049
  invitationId: string;
2040
2050
  }): Promise<void>;
2051
+ /**
2052
+ * Report the deployment's auth configuration — enabled plugins, sign-in
2053
+ * methods, user-settable create-user fields, organization sub-features
2054
+ * (teams / roles), and session / rate-limit policy. Drives the config panel
2055
+ * and the dynamic create-user form. Never carries a secret.
2056
+ */
2057
+ getAuthConfig(): Promise<AuthConfigInfo>;
2058
+ /** Create an organization; optionally seed an `owner` member for `ownerId`. */
2059
+ createAuthOrganization(input: {
2060
+ logo?: string;
2061
+ metadata?: Record<string, unknown>;
2062
+ name: string;
2063
+ ownerId?: string;
2064
+ slug?: string;
2065
+ }): Promise<Record<string, unknown>>;
2066
+ /** Update an organization's name/slug/logo/metadata. */
2067
+ updateAuthOrganization(input: {
2068
+ logo?: string;
2069
+ metadata?: Record<string, unknown>;
2070
+ name?: string;
2071
+ organizationId: string;
2072
+ slug?: string;
2073
+ }): Promise<Record<string, unknown>>;
2074
+ /** Delete an organization and cascade its members, invitations, teams, and custom roles. */
2075
+ deleteAuthOrganization(input: {
2076
+ organizationId: string;
2077
+ }): Promise<void>;
2078
+ /** Directly add an existing user to an organization (no invitation/acceptance). */
2079
+ addAuthOrgMember(input: {
2080
+ organizationId: string;
2081
+ role?: string;
2082
+ userId: string;
2083
+ }): Promise<Record<string, unknown>>;
2084
+ /** Create a pending email invitation to an organization. */
2085
+ inviteAuthOrgMember(input: {
2086
+ email: string;
2087
+ inviterId?: string;
2088
+ organizationId: string;
2089
+ role?: string;
2090
+ }): Promise<Record<string, unknown>>;
2091
+ /** Change a member's role. */
2092
+ setAuthOrgMemberRole(input: {
2093
+ memberId: string;
2094
+ role: string | string[];
2095
+ }): Promise<Record<string, unknown>>;
2096
+ /** List an organization's teams (requires the organization plugin with teams enabled). */
2097
+ listAuthOrgTeams(input: {
2098
+ limit?: number;
2099
+ offset?: number;
2100
+ organizationId: string;
2101
+ }): Promise<AuthPage<Record<string, unknown>>>;
2102
+ /** Create a team under an organization. */
2103
+ createAuthOrgTeam(input: {
2104
+ name: string;
2105
+ organizationId: string;
2106
+ }): Promise<Record<string, unknown>>;
2107
+ /** Rename a team. */
2108
+ updateAuthOrgTeam(input: {
2109
+ name: string;
2110
+ teamId: string;
2111
+ }): Promise<Record<string, unknown>>;
2112
+ /** Delete a team and its memberships. */
2113
+ removeAuthOrgTeam(input: {
2114
+ teamId: string;
2115
+ }): Promise<void>;
2116
+ /** List a team's members. */
2117
+ listAuthOrgTeamMembers(input: {
2118
+ limit?: number;
2119
+ offset?: number;
2120
+ teamId: string;
2121
+ }): Promise<AuthPage<Record<string, unknown>>>;
2122
+ /** Add a user to a team. */
2123
+ addAuthOrgTeamMember(input: {
2124
+ teamId: string;
2125
+ userId: string;
2126
+ }): Promise<Record<string, unknown>>;
2127
+ /** Remove a member from a team. */
2128
+ removeAuthOrgTeamMember(input: {
2129
+ teamMemberId: string;
2130
+ }): Promise<void>;
2131
+ /** List an organization's custom roles (requires the organization plugin with dynamic access control). */
2132
+ listAuthOrgRoles(input: {
2133
+ limit?: number;
2134
+ offset?: number;
2135
+ organizationId: string;
2136
+ }): Promise<AuthPage<Record<string, unknown>>>;
2137
+ /** Create a custom org role with a permission grant (a `resource -> actions[]` map). */
2138
+ createAuthOrgRole(input: {
2139
+ organizationId: string;
2140
+ permission: Record<string, string[]>;
2141
+ role: string;
2142
+ }): Promise<Record<string, unknown>>;
2143
+ /** Replace a custom org role's permission grant. */
2144
+ updateAuthOrgRole(input: {
2145
+ permission: Record<string, string[]>;
2146
+ roleId: string;
2147
+ }): Promise<Record<string, unknown>>;
2148
+ /** Delete a custom org role. */
2149
+ deleteAuthOrgRole(input: {
2150
+ roleId: string;
2151
+ }): Promise<void>;
2041
2152
  /** List auth sessions, paged and optionally filtered to one user. */
2042
2153
  listAuthSessions(options?: {
2043
2154
  limit?: number;
@@ -1,4 +1,4 @@
1
- import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-CPMaTnsC.mjs";
1
+ import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-Dy4neKF6.mjs";
2
2
  /**
3
3
  * Run a query once on the server (during SSR) and capture its result in a
4
4
  * serializable {@link Preloaded} token. Embed the token in the rendered HTML and
@@ -1,4 +1,4 @@
1
- import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-CPMaTnsC.js";
1
+ import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-Dy4neKF6.js";
2
2
  /**
3
3
  * Run a query once on the server (during SSR) and capture its result in a
4
4
  * serializable {@link Preloaded} token. Embed the token in the rendered HTML and
@@ -1,5 +1,5 @@
1
- import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-CPMaTnsC.mjs";
2
- export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-CPMaTnsC.mjs";
1
+ import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-Dy4neKF6.mjs";
2
+ export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-Dy4neKF6.mjs";
3
3
  import '@lunora/runtime';
4
4
  /**
5
5
  * The sentinel a framework adapter resolves its reactive args to when it wants
@@ -1,5 +1,5 @@
1
- import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-CPMaTnsC.js";
2
- export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-CPMaTnsC.js";
1
+ import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-Dy4neKF6.js";
2
+ export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-Dy4neKF6.js";
3
3
  import '@lunora/runtime';
4
4
  /**
5
5
  * The sentinel a framework adapter resolves its reactive args to when it wants
@@ -1,6 +1,6 @@
1
- import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-CPMaTnsC.mjs";
2
- export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-CPMaTnsC.mjs";
3
- export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-Bl3z1rPo.mjs";
1
+ import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-Dy4neKF6.mjs";
2
+ export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-Dy4neKF6.mjs";
3
+ export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-BQaCmS5J.mjs";
4
4
  import '@lunora/runtime';
5
5
  /**
6
6
  * Structural shape of a better-auth `getSession` call's resolved value.
@@ -1,6 +1,6 @@
1
- import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-CPMaTnsC.js";
2
- export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-CPMaTnsC.js";
3
- export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-DH0CqSxy.js";
1
+ import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-Dy4neKF6.js";
2
+ export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-Dy4neKF6.js";
3
+ export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-DI-5eqHP.js";
4
4
  import '@lunora/runtime';
5
5
  /**
6
6
  * Structural shape of a better-auth `getSession` call's resolved value.
@@ -1,4 +1,4 @@
1
1
  export { getServerSession } from '../packem_shared/getServerSession-8jXewqxd.mjs';
2
2
  export { deserializePreloaded, serializePreloaded } from '../packem_shared/deserializePreloaded-C0eJTY_W.mjs';
3
- export { createServerClient } from '../packem_shared/createServerClient-CFrM8ZQO.mjs';
3
+ export { createServerClient } from '../packem_shared/createServerClient-Cet4TATX.mjs';
4
4
  export { preloadQuery, preloadedQueryResult } from '../packem_shared/preloadQuery-lobFkD2Z.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/client",
3
- "version": "1.0.0-alpha.16",
3
+ "version": "1.0.0-alpha.18",
4
4
  "description": "Lunora browser SDK: WebSocket transport, optimistic updates, and an offline mutation queue",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -61,6 +61,9 @@
61
61
  "publishConfig": {
62
62
  "access": "public"
63
63
  },
64
+ "dependencies": {
65
+ "@lunora/errors": "1.0.0-alpha.1"
66
+ },
64
67
  "engines": {
65
68
  "node": "^22.15.0 || >=24.11.0"
66
69
  }