@classytic/arc-next 0.11.1 → 0.13.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.
@@ -1,6 +1,4 @@
1
1
  import { QueryKeys } from "./cache.js";
2
- import * as _$_tanstack_react_query0 from "@tanstack/react-query";
3
-
4
2
  //#region src/query-options.d.ts
5
3
  /** Per-call request context: auth + Next.js fetch caching passthrough. */
6
4
  interface QueryFnContext {
@@ -91,57 +89,65 @@ type EntityQueries = ReturnType<typeof createEntityQueries>;
91
89
  * await queryClient.ensureQueryData(productQueries.detail(id, { token }));
92
90
  */
93
91
  declare function createEntityQueries(api: EntityReadApi, entityKey: string): {
94
- /** The entity's key factory — for invalidation / setQueryData at call sites. */keys: QueryKeys; /** GET /:resource — mirrors `useList`'s key (scoped, org-normalized). */
95
- list(params?: Record<string, unknown>, ctx?: QueryFnContext): _$_tanstack_react_query0.OmitKeyof<_$_tanstack_react_query0.UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
96
- queryFn?: _$_tanstack_react_query0.QueryFunction<unknown, readonly unknown[], never> | undefined;
92
+ /** The entity's key factory — for invalidation / setQueryData at call sites. */
93
+ keys: QueryKeys;
94
+ /** GET /:resource — mirrors `useList`'s key (scoped, org-normalized). */
95
+ list(params?: Record<string, unknown>, ctx?: QueryFnContext): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
96
+ queryFn?: import("@tanstack/react-query").QueryFunction<unknown, readonly unknown[], never> | undefined;
97
97
  } & {
98
98
  queryKey: readonly unknown[] & {
99
99
  [dataTagSymbol]: unknown;
100
100
  [dataTagErrorSymbol]: Error;
101
101
  };
102
- }; /** GET /:resource/:id — mirrors `useDetail`'s scoped key (+ params variant). */
103
- detail(id: string, opts?: DetailQueryOpts): _$_tanstack_react_query0.OmitKeyof<_$_tanstack_react_query0.UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
104
- queryFn?: _$_tanstack_react_query0.QueryFunction<unknown, readonly unknown[], never> | undefined;
102
+ };
103
+ /** GET /:resource/:id mirrors `useDetail`'s scoped key (+ params variant). */
104
+ detail(id: string, opts?: DetailQueryOpts): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
105
+ queryFn?: import("@tanstack/react-query").QueryFunction<unknown, readonly unknown[], never> | undefined;
105
106
  } & {
106
107
  queryKey: readonly unknown[] & {
107
108
  [dataTagSymbol]: unknown;
108
109
  [dataTagErrorSymbol]: Error;
109
110
  };
110
- }; /** GET /:resource/slug/:slug — mirrors `useDetailBySlug`'s key. */
111
- bySlug(slug: string, opts?: DetailQueryOpts): _$_tanstack_react_query0.OmitKeyof<_$_tanstack_react_query0.UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
112
- queryFn?: _$_tanstack_react_query0.QueryFunction<unknown, readonly unknown[], never> | undefined;
111
+ };
112
+ /** GET /:resource/slug/:slug mirrors `useDetailBySlug`'s key. */
113
+ bySlug(slug: string, opts?: DetailQueryOpts): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
114
+ queryFn?: import("@tanstack/react-query").QueryFunction<unknown, readonly unknown[], never> | undefined;
113
115
  } & {
114
116
  queryKey: readonly unknown[] & {
115
117
  [dataTagSymbol]: unknown;
116
118
  [dataTagErrorSymbol]: Error;
117
119
  };
118
- }; /** GET /:resource/deleted — mirrors `useDeleted`'s key. */
119
- deleted(params?: Record<string, unknown>, ctx?: QueryFnContext): _$_tanstack_react_query0.OmitKeyof<_$_tanstack_react_query0.UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
120
- queryFn?: _$_tanstack_react_query0.QueryFunction<unknown, readonly unknown[], never> | undefined;
120
+ };
121
+ /** GET /:resource/deleted mirrors `useDeleted`'s key. */
122
+ deleted(params?: Record<string, unknown>, ctx?: QueryFnContext): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
123
+ queryFn?: import("@tanstack/react-query").QueryFunction<unknown, readonly unknown[], never> | undefined;
121
124
  } & {
122
125
  queryKey: readonly unknown[] & {
123
126
  [dataTagSymbol]: unknown;
124
127
  [dataTagErrorSymbol]: Error;
125
128
  };
126
- }; /** GET /:resource/tree — mirrors `useTree`'s key. */
127
- tree(params?: Record<string, unknown>, ctx?: QueryFnContext): _$_tanstack_react_query0.OmitKeyof<_$_tanstack_react_query0.UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
128
- queryFn?: _$_tanstack_react_query0.QueryFunction<unknown, readonly unknown[], never> | undefined;
129
+ };
130
+ /** GET /:resource/tree mirrors `useTree`'s key. */
131
+ tree(params?: Record<string, unknown>, ctx?: QueryFnContext): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
132
+ queryFn?: import("@tanstack/react-query").QueryFunction<unknown, readonly unknown[], never> | undefined;
129
133
  } & {
130
134
  queryKey: readonly unknown[] & {
131
135
  [dataTagSymbol]: unknown;
132
136
  [dataTagErrorSymbol]: Error;
133
137
  };
134
- }; /** GET /:resource/:parentId/children — mirrors `useChildren`'s key. */
135
- children(parentId: string, params?: Record<string, unknown>, ctx?: QueryFnContext): _$_tanstack_react_query0.OmitKeyof<_$_tanstack_react_query0.UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
136
- queryFn?: _$_tanstack_react_query0.QueryFunction<unknown, readonly unknown[], never> | undefined;
138
+ };
139
+ /** GET /:resource/:parentId/children mirrors `useChildren`'s key. */
140
+ children(parentId: string, params?: Record<string, unknown>, ctx?: QueryFnContext): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
141
+ queryFn?: import("@tanstack/react-query").QueryFunction<unknown, readonly unknown[], never> | undefined;
137
142
  } & {
138
143
  queryKey: readonly unknown[] & {
139
144
  [dataTagSymbol]: unknown;
140
145
  [dataTagErrorSymbol]: Error;
141
146
  };
142
- }; /** GET /:resource/aggregations/:name — mirrors `useAggregation`'s tenant-scoped key. */
143
- aggregation(name: string, filter?: Record<string, unknown>, ctx?: QueryFnContext): _$_tanstack_react_query0.OmitKeyof<_$_tanstack_react_query0.UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
144
- queryFn?: _$_tanstack_react_query0.QueryFunction<unknown, readonly unknown[], never> | undefined;
147
+ };
148
+ /** GET /:resource/aggregations/:name mirrors `useAggregation`'s tenant-scoped key. */
149
+ aggregation(name: string, filter?: Record<string, unknown>, ctx?: QueryFnContext): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<unknown, Error, unknown, readonly unknown[]>, "queryFn"> & {
150
+ queryFn?: import("@tanstack/react-query").QueryFunction<unknown, readonly unknown[], never> | undefined;
145
151
  } & {
146
152
  queryKey: readonly unknown[] & {
147
153
  [dataTagSymbol]: unknown;
@@ -152,11 +158,11 @@ declare function createEntityQueries(api: EntityReadApi, entityKey: string): {
152
158
  * Infinite list — mirrors `useInfiniteList`'s key (`scopedList + 'infinite'`)
153
159
  * and its page-param semantics (keyset cursor or offset page + 1).
154
160
  */
155
- infiniteList(params?: Record<string, unknown>, ctx?: QueryFnContext): _$_tanstack_react_query0.OmitKeyof<_$_tanstack_react_query0.UseInfiniteQueryOptions<unknown, Error, _$_tanstack_react_query0.InfiniteData<unknown, unknown>, unknown[], unknown>, "queryFn"> & {
156
- queryFn?: _$_tanstack_react_query0.QueryFunction<unknown, unknown[], unknown> | undefined;
161
+ infiniteList(params?: Record<string, unknown>, ctx?: QueryFnContext): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseInfiniteQueryOptions<unknown, Error, import("@tanstack/react-query").InfiniteData<unknown, unknown>, unknown[], unknown>, "queryFn"> & {
162
+ queryFn?: import("@tanstack/react-query").QueryFunction<unknown, unknown[], unknown> | undefined;
157
163
  } & {
158
164
  queryKey: unknown[] & {
159
- [dataTagSymbol]: _$_tanstack_react_query0.InfiniteData<unknown, unknown>;
165
+ [dataTagSymbol]: import("@tanstack/react-query").InfiniteData<unknown, unknown>;
160
166
  [dataTagErrorSymbol]: Error;
161
167
  };
162
168
  };
package/dist/query.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { CacheUtils, DEFAULT_QUERY_CONFIG, PaginationData, QUERY_CONFIGS, QueryKeys, createCacheUtils, createQueryKeys, extractItem, extractItems, getItemId, normalizePagination, updateListCache } from "./cache.js";
2
2
  import { InfiniteData, QueryClient, QueryKey } from "@tanstack/react-query";
3
-
4
3
  //#region src/query.d.ts
5
4
  /** Request-level options passed through to the fetch call */
6
5
  interface RequestPassthrough {
@@ -143,13 +142,7 @@ interface CreateListQueryConfig {
143
142
  * directly via `placeholderData`, so the detail GET still fires while the
144
143
  * consumer sees an instant list-shaped preview. See `findItemInListCache`.
145
144
  */
146
- declare function useListQuery<T>({
147
- queryKey,
148
- queryFn,
149
- enabled,
150
- options,
151
- select
152
- }: CreateListQueryConfig): ListQueryResult<T>;
145
+ declare function useListQuery<T>({ queryKey, queryFn, enabled, options, select }: CreateListQueryConfig): ListQueryResult<T>;
153
146
  /**
154
147
  * Find an item in any list cache for this entity by ID.
155
148
  *
@@ -187,28 +180,11 @@ interface CreateDetailQueryConfig<T = unknown> {
187
180
  */
188
181
  placeholderData?: () => T | undefined;
189
182
  }
190
- declare function useDetailQuery<T>({
191
- queryKey,
192
- queryFn,
193
- enabled,
194
- options,
195
- select,
196
- placeholderData
197
- }: CreateDetailQueryConfig<T>): DetailQueryResult<T>;
183
+ declare function useDetailQuery<T>({ queryKey, queryFn, enabled, options, select, placeholderData }: CreateDetailQueryConfig<T>): DetailQueryResult<T>;
198
184
  /** Suspense variant of {@link useListQuery}. Always enabled; suspends until resolved. */
199
- declare function useSuspenseListQuery<T>({
200
- queryKey,
201
- queryFn,
202
- options,
203
- select
204
- }: Omit<CreateListQueryConfig, "enabled">): ListQueryResult<T>;
185
+ declare function useSuspenseListQuery<T>({ queryKey, queryFn, options, select }: Omit<CreateListQueryConfig, "enabled">): ListQueryResult<T>;
205
186
  /** Suspense variant of {@link useDetailQuery}. Always enabled; suspends until resolved. */
206
- declare function useSuspenseDetailQuery<T>({
207
- queryKey,
208
- queryFn,
209
- options,
210
- select
211
- }: Omit<CreateDetailQueryConfig<T>, "enabled" | "placeholderData">): DetailQueryResult<T>;
187
+ declare function useSuspenseDetailQuery<T>({ queryKey, queryFn, options, select }: Omit<CreateDetailQueryConfig<T>, "enabled" | "placeholderData">): DetailQueryResult<T>;
212
188
  interface InfiniteListQueryOptions {
213
189
  public?: boolean;
214
190
  enabled?: boolean;
@@ -257,16 +233,7 @@ interface CreateInfiniteListQueryConfig {
257
233
  /** Max pages to keep in memory. Old pages are evicted when exceeded. */
258
234
  maxPages?: number;
259
235
  }
260
- declare function useInfiniteListQuery<T>({
261
- queryKey,
262
- queryFn,
263
- enabled,
264
- options,
265
- initialPageParam,
266
- getNextPageParam,
267
- getPreviousPageParam,
268
- maxPages
269
- }: CreateInfiniteListQueryConfig): InfiniteListQueryResult<T>;
236
+ declare function useInfiniteListQuery<T>({ queryKey, queryFn, enabled, options, initialPageParam, getNextPageParam, getPreviousPageParam, maxPages }: CreateInfiniteListQueryConfig): InfiniteListQueryResult<T>;
270
237
  /** Recognized data-freshness presets. Maps to QUERY_CONFIGS. */
271
238
  type QueryFreshness = keyof typeof QUERY_CONFIGS;
272
239
  /**
@@ -286,7 +253,7 @@ interface UseApiQueryOptions {
286
253
  refetchIntervalInBackground?: boolean;
287
254
  retry?: boolean | number;
288
255
  /** Limit re-renders to changes in these specific fields (perf optimization). */
289
- notifyOnChangeProps?: ('data' | 'error' | 'isLoading' | 'isFetching' | 'isError' | 'isSuccess' | 'isStale')[];
256
+ notifyOnChangeProps?: ("data" | "error" | "isLoading" | "isFetching" | "isError" | "isSuccess" | "isStale")[];
290
257
  }
291
258
  interface UseApiQueryConfig<TResponse, TData> {
292
259
  queryKey: QueryKey;
@@ -342,13 +309,6 @@ interface UseApiQueryResult<TData> {
342
309
  * select: (res) => res.entries,
343
310
  * });
344
311
  */
345
- declare function useApiQuery<TResponse = unknown, TData = ExtractData<TResponse>>({
346
- queryKey,
347
- queryFn,
348
- enabled,
349
- freshness,
350
- select,
351
- options
352
- }: UseApiQueryConfig<TResponse, TData>): UseApiQueryResult<TData>;
312
+ declare function useApiQuery<TResponse = unknown, TData = ExtractData<TResponse>>({ queryKey, queryFn, enabled, freshness, select, options }: UseApiQueryConfig<TResponse, TData>): UseApiQueryResult<TData>;
353
313
  //#endregion
354
314
  export { type CacheUtils, CreateDetailQueryConfig, CreateInfiniteListQueryConfig, CreateListQueryConfig, DEFAULT_QUERY_CONFIG, DetailQueryOptions, DetailQueryResult, ExtractData, InfiniteListQueryOptions, InfiniteListQueryResult, ListQueryOptions, ListQueryResult, type PaginationData, QUERY_CONFIGS, QueryFreshness, type QueryKeys, RequestPassthrough, UseApiQueryConfig, UseApiQueryOptions, UseApiQueryResult, createCacheUtils, createQueryKeys, extractItem, extractItems, findItemInListCache, getItemId, normalizePagination, updateListCache, useApiQuery, useDetailQuery, useInfiniteListQuery, useListQuery, useSuspenseDetailQuery, useSuspenseListQuery };
package/dist/sse.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { QueryKey } from "@tanstack/react-query";
2
-
3
2
  //#region src/sse.d.ts
4
3
  /**
5
4
  * Build an authenticated SSE URL using the global client + auth singletons.
package/dist/sse.js CHANGED
@@ -113,13 +113,14 @@ function subscribeToEvents(options) {
113
113
  } catch {
114
114
  payload = event.data;
115
115
  }
116
- dispatch(typeof payload === "object" && payload !== null && "type" in payload && "data" in payload ? payload : {
116
+ const parsed = typeof payload === "object" && payload !== null && "type" in payload && "data" in payload ? payload : {
117
117
  type: eventType,
118
118
  resource: resource ?? eventType.split(".")[0] ?? "",
119
119
  data: payload,
120
120
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
121
121
  ...event.lastEventId ? { id: event.lastEventId } : {}
122
- });
122
+ };
123
+ dispatch(parsed);
123
124
  });
124
125
  es.onerror = () => {
125
126
  try {
@@ -166,7 +167,7 @@ function subscribeToEvents(options) {
166
167
  const scheduleReconnect = () => {
167
168
  if (reconnectAttempts < maxReconnectAttempts) {
168
169
  reconnectAttempts += 1;
169
- const delay = Math.min(reconnectDelay * Math.pow(1.5, reconnectAttempts - 1), 3e4);
170
+ const delay = Math.min(reconnectDelay * 1.5 ** (reconnectAttempts - 1), 3e4);
170
171
  reconnectTimer = setTimeout(connect, delay);
171
172
  }
172
173
  };
package/dist/upload.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ArcClient, HttpMethod, ToastHandler } from "./client.js";
2
2
  import { MutationMessages } from "./mutation.js";
3
3
  import { QueryKey } from "@tanstack/react-query";
4
-
5
4
  //#region src/upload.d.ts
6
5
  /**
7
6
  * Upload-progress snapshot. Emitted on every native `xhr.upload.progress`
@@ -71,6 +70,15 @@ interface UploadWithProgressOptions {
71
70
  * an image and returns the resized binary). Default: false (parse JSON).
72
71
  */
73
72
  responseType?: "json" | "text" | "blob";
73
+ /**
74
+ * Upload timeout in ms, assigned to `xhr.timeout` — the whole request
75
+ * (upload + server processing + response) must finish within this window
76
+ * or the promise rejects with a `TimeoutError`. Default: disabled (0) —
77
+ * large files on slow links legitimately take minutes; size it to your
78
+ * payload ceiling when you enable it. (`ClientConfig.timeoutMs` does NOT
79
+ * apply to uploads — the fetch pipeline and XHR transport stay isolated.)
80
+ */
81
+ timeoutMs?: number;
74
82
  }
75
83
  /**
76
84
  * Upload a `FormData` payload via XHR with native progress events.
package/dist/upload.js CHANGED
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  import { ArcApiError, _getAuthErrorHandler, _isAuthRecoverable, _resolveRefreshedToken, _runAuthRecovery, getAuthMode, getBaseUrl, getClientAuthContext } from "./client.js";
2
4
  import { getToastHandler } from "./mutation.js";
3
5
  import { useQueryClient } from "@tanstack/react-query";
@@ -110,7 +112,7 @@ async function uploadWithProgress(options) {
110
112
  * in the outer loop; this function just performs one upload.
111
113
  */
112
114
  function uploadAttempt(options) {
113
- const { url, formData, method = "POST", onProgress, signal, client, headers: extraHeaders, elevated, idempotencyKey, responseType = "json" } = options;
115
+ const { url, formData, method = "POST", onProgress, signal, client, headers: extraHeaders, elevated, idempotencyKey, responseType = "json", timeoutMs = 0 } = options;
114
116
  return new Promise((resolve, reject) => {
115
117
  if (signal?.aborted) {
116
118
  reject(abortReason(signal));
@@ -119,6 +121,7 @@ function uploadAttempt(options) {
119
121
  const xhr = new XMLHttpRequest();
120
122
  const fullUrl = resolveUrl(url, client);
121
123
  xhr.open(method, fullUrl, true);
124
+ if (timeoutMs > 0) xhr.timeout = timeoutMs;
122
125
  xhr.responseType = responseType === "blob" ? "blob" : "";
123
126
  const authMode = client?.config?.authMode ?? getAuthMode();
124
127
  if (authMode === "cookie") xhr.withCredentials = true;
@@ -130,7 +133,7 @@ function uploadAttempt(options) {
130
133
  if (authMode === "header") {
131
134
  const headerName = client?.auth?.headerName ?? "x-api-key";
132
135
  builtHeaders[headerName] = token;
133
- } else if (authMode !== "cookie") builtHeaders["Authorization"] = `Bearer ${token}`;
136
+ } else if (authMode !== "cookie") builtHeaders.Authorization = `Bearer ${token}`;
134
137
  }
135
138
  if (orgId) builtHeaders["x-organization-id"] = orgId;
136
139
  if (elevated ?? client?.config?.elevated) builtHeaders["x-arc-scope"] = "platform";
@@ -147,8 +150,9 @@ function uploadAttempt(options) {
147
150
  const lengthComputable = event.lengthComputable;
148
151
  const total = lengthComputable ? event.total : 0;
149
152
  const loaded = event.loaded;
153
+ const percent = lengthComputable && total > 0 ? Math.min(100, Math.round(loaded / total * 100)) : 0;
150
154
  onProgress({
151
- percent: lengthComputable && total > 0 ? Math.min(100, Math.round(loaded / total * 100)) : 0,
155
+ percent,
152
156
  loaded,
153
157
  total,
154
158
  lengthComputable
@@ -191,7 +195,7 @@ function uploadAttempt(options) {
191
195
  };
192
196
  xhr.ontimeout = () => {
193
197
  if (abortListener && signal) signal.removeEventListener("abort", abortListener);
194
- reject(/* @__PURE__ */ new Error(`Upload timed out: ${fullUrl}`));
198
+ reject(Object.assign(/* @__PURE__ */ new Error(`Upload timed out after ${timeoutMs}ms: ${fullUrl}`), { name: "TimeoutError" }));
195
199
  };
196
200
  xhr.send(formData);
197
201
  });
package/dist/ws.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { QueryKey } from "@tanstack/react-query";
2
-
3
2
  //#region src/ws.d.ts
4
3
  /**
5
4
  * Inbound message shape from Arc's `websocketPlugin` broadcasts.
@@ -21,7 +20,7 @@ interface ArcWsMessage<TData = unknown> {
21
20
  * Backend also accepts `channel` as alias.
22
21
  */
23
22
  interface ArcSubscribeFrame {
24
- type: 'subscribe' | 'unsubscribe';
23
+ type: "subscribe" | "unsubscribe";
25
24
  resource?: string;
26
25
  channel?: string;
27
26
  /** Free-form additional fields the backend may use (token, filters, etc.). */
package/dist/ws.js CHANGED
@@ -150,7 +150,7 @@ function connectWs(options = {}) {
150
150
  }
151
151
  if (reconnectAttempts < maxReconnectAttempts) {
152
152
  reconnectAttempts += 1;
153
- const delay = Math.min(reconnectDelay * Math.pow(1.5, reconnectAttempts - 1), 3e4);
153
+ const delay = Math.min(reconnectDelay * 1.5 ** (reconnectAttempts - 1), 3e4);
154
154
  reconnectTimer = setTimeout(connect, delay);
155
155
  }
156
156
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/arc-next",
3
- "version": "0.11.1",
3
+ "version": "0.13.0",
4
4
  "description": "React + TanStack Query SDK for Arc resources",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -8,7 +8,7 @@
8
8
  "author": "Classytic",
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "https://github.com/classytic/arc-next"
11
+ "url": "git+https://github.com/classytic/arc-next.git"
12
12
  },
13
13
  "keywords": [
14
14
  "react",
@@ -136,11 +136,19 @@
136
136
  "push": "classytic-push",
137
137
  "release:tag": "node -e \"require('child_process').execSync('npm run push -- v'+require('./package.json').version,{stdio:'inherit'})\"",
138
138
  "release": "npm run push -- main && npm run release:tag && npm publish",
139
- "prepublishOnly": "npm run typecheck && npm test && npm run build",
140
- "typecheck:tests": "tsc --noEmit -p tsconfig.test.json"
139
+ "prepublishOnly": "npm run typecheck && npm run typecheck:tests && npm run lint && npm run check:dead-code && npm test && npm run build && npm run check:package && npm run check:api-surface && npm run check:server-import && npm run check:bundle && npm run check:fixtures",
140
+ "typecheck:tests": "tsc --noEmit -p tsconfig.test.json",
141
+ "check:package": "publint --strict && attw --pack . --profile esm-only",
142
+ "check:api-surface": "node scripts/check-api-surface.mjs",
143
+ "api:surface": "node scripts/check-api-surface.mjs --update",
144
+ "check:server-import": "node scripts/check-server-import.mjs",
145
+ "check:bundle": "node scripts/check-bundle-size.mjs",
146
+ "check:fixtures": "tsc -p fixtures/tsconfig.json",
147
+ "lint": "biome check src/ tests/ scripts/ fixtures/",
148
+ "check:dead-code": "knip"
141
149
  },
142
150
  "peerDependencies": {
143
- "@classytic/repo-core": ">=0.4.0",
151
+ "@classytic/repo-core": ">=0.14.0",
144
152
  "@tanstack/react-query": ">=5.62.0",
145
153
  "jose": ">=5.0.0",
146
154
  "react": ">=19.0.0"
@@ -160,18 +168,21 @@
160
168
  }
161
169
  },
162
170
  "devDependencies": {
171
+ "@arethetypeswrong/cli": "^0.18.5",
172
+ "@biomejs/biome": "^2.5.5",
163
173
  "@classytic/dev-tools": "^0.2.0",
164
- "@classytic/repo-core": "^0.5.0",
174
+ "@classytic/repo-core": "^0.19.0",
165
175
  "@tanstack/react-query": "^5.97.0",
166
- "@testing-library/jest-dom": "^6.9.1",
167
176
  "@testing-library/react": "^16.3.2",
168
177
  "@types/react": "^19.2.14",
169
178
  "@types/react-dom": "^19.2.3",
170
179
  "jose": "^6.2.3",
171
180
  "jsdom": "^29.0.2",
181
+ "knip": "^6.27.0",
182
+ "publint": "^0.3.21",
172
183
  "react": "^19.2.5",
173
184
  "react-dom": "^19.2.5",
174
- "tsdown": "^0.21.7",
185
+ "tsdown": "^0.22.14",
175
186
  "typescript": "^6.0.2",
176
187
  "vitest": "^4.1.4"
177
188
  }