@sylphx/lens-solid 2.1.1 → 2.1.2

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/dist/create.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * @sylphx/lens-solid - Create Client
3
3
  *
4
4
  * Creates a typed Lens client with SolidJS primitives.
5
- * Each endpoint can be called directly as a primitive or via .fetch() for promises.
5
+ * Base client methods work in vanilla JS, primitives are extensions.
6
6
  *
7
7
  * @example
8
8
  * ```tsx
@@ -15,18 +15,20 @@
15
15
  * transport: httpTransport({ url: '/api/lens' }),
16
16
  * });
17
17
  *
18
- * // In component
19
- * const { data, loading } = client.user.get({ input: { id } });
18
+ * // Vanilla JS (anywhere - SSR, utilities, event handlers)
19
+ * const user = await client.user.get({ input: { id } });
20
+ * client.user.get({ input: { id } }).subscribe(data => console.log(data));
20
21
  *
21
- * // In SSR
22
- * const user = await client.user.get.fetch({ input: { id } });
22
+ * // SolidJS primitives (in components)
23
+ * const { data, loading } = client.user.get.createQuery({ input: { id } });
24
+ * const { mutate, loading } = client.user.create.createMutation();
23
25
  * ```
24
26
  */
25
- import { type LensClientConfig, type SelectionObject, type TypedClientConfig } from "@sylphx/lens-client";
27
+ import { type LensClientConfig, type QueryResult, type SelectionObject, type TypedClientConfig } from "@sylphx/lens-client";
26
28
  import type { MutationDef, QueryDef, RouterDef, RouterRoutes } from "@sylphx/lens-core";
27
29
  import { type Accessor } from "solid-js";
28
- /** Query hook options */
29
- export interface QueryHookOptions<TInput> {
30
+ /** Query primitive options */
31
+ export interface QueryPrimitiveOptions<TInput> {
30
32
  /** Query input parameters */
31
33
  input?: TInput;
32
34
  /** Field selection */
@@ -34,8 +36,8 @@ export interface QueryHookOptions<TInput> {
34
36
  /** Skip query execution */
35
37
  skip?: boolean;
36
38
  }
37
- /** Query hook result */
38
- export interface QueryHookResult<T> {
39
+ /** Query primitive result */
40
+ export interface QueryPrimitiveResult<T> {
39
41
  /** Reactive data accessor */
40
42
  data: Accessor<T | null>;
41
43
  /** Reactive loading state */
@@ -45,8 +47,8 @@ export interface QueryHookResult<T> {
45
47
  /** Refetch the query */
46
48
  refetch: () => void;
47
49
  }
48
- /** Mutation hook options */
49
- export interface MutationHookOptions<TOutput> {
50
+ /** Mutation primitive options */
51
+ export interface MutationPrimitiveOptions<TOutput> {
50
52
  /** Called on successful mutation */
51
53
  onSuccess?: (data: TOutput) => void;
52
54
  /** Called on mutation error */
@@ -54,8 +56,8 @@ export interface MutationHookOptions<TOutput> {
54
56
  /** Called when mutation settles (success or error) */
55
57
  onSettled?: () => void;
56
58
  }
57
- /** Mutation hook result */
58
- export interface MutationHookResult<TInput, TOutput> {
59
+ /** Mutation primitive result */
60
+ export interface MutationPrimitiveResult<TInput, TOutput> {
59
61
  /** Execute the mutation */
60
62
  mutate: (options: {
61
63
  input: TInput;
@@ -70,28 +72,27 @@ export interface MutationHookResult<TInput, TOutput> {
70
72
  /** Reset mutation state */
71
73
  reset: () => void;
72
74
  }
73
- /** Query endpoint type */
75
+ /** Query endpoint with SolidJS primitives */
74
76
  export interface QueryEndpoint<TInput, TOutput> {
75
- /** Primitive call (in component) */
76
- <_TSelect extends SelectionObject = Record<string, never>>(options: TInput extends void ? QueryHookOptions<void> | void : QueryHookOptions<TInput>): QueryHookResult<TOutput>;
77
- /** Promise call (SSR) */
78
- fetch: <TSelect extends SelectionObject = Record<string, never>>(options: TInput extends void ? {
79
- input?: void;
80
- select?: TSelect;
81
- } | void : {
82
- input: TInput;
83
- select?: TSelect;
84
- }) => Promise<TOutput>;
77
+ /** Vanilla JS call - returns QueryResult (Promise + Observable) */
78
+ (options?: {
79
+ input?: TInput;
80
+ select?: SelectionObject;
81
+ }): QueryResult<TOutput>;
82
+ /** SolidJS primitive for reactive queries */
83
+ createQuery: (options?: TInput extends void ? QueryPrimitiveOptions<void> | void : QueryPrimitiveOptions<TInput>) => QueryPrimitiveResult<TOutput>;
85
84
  }
86
- /** Mutation endpoint type */
85
+ /** Mutation endpoint with SolidJS primitives */
87
86
  export interface MutationEndpoint<TInput, TOutput> {
88
- /** Primitive call (in component) */
89
- (options?: MutationHookOptions<TOutput>): MutationHookResult<TInput, TOutput>;
90
- /** Promise call (SSR) */
91
- fetch: <TSelect extends SelectionObject = Record<string, never>>(options: {
87
+ /** Vanilla JS call - returns Promise */
88
+ (options: {
92
89
  input: TInput;
93
- select?: TSelect;
94
- }) => Promise<TOutput>;
90
+ select?: SelectionObject;
91
+ }): Promise<{
92
+ data: TOutput;
93
+ }>;
94
+ /** SolidJS primitive for mutations */
95
+ createMutation: (options?: MutationPrimitiveOptions<TOutput>) => MutationPrimitiveResult<TInput, TOutput>;
95
96
  }
96
97
  /** Infer client type from router routes */
97
98
  type InferTypedClient<TRoutes extends RouterRoutes> = {
@@ -102,9 +103,8 @@ export type TypedClient<TRouter extends RouterDef> = TRouter extends RouterDef<i
102
103
  /**
103
104
  * Create a Lens client with SolidJS primitives.
104
105
  *
105
- * Each endpoint can be called:
106
- * - Directly as a primitive: `client.user.get({ input: { id } })`
107
- * - Via .fetch() for promises: `await client.user.get.fetch({ input: { id } })`
106
+ * Base client methods work in vanilla JS (SSR, utilities, event handlers).
107
+ * SolidJS primitives are available as `.createQuery()` and `.createMutation()`.
108
108
  *
109
109
  * @example
110
110
  * ```tsx
@@ -117,14 +117,16 @@ export type TypedClient<TRouter extends RouterDef> = TRouter extends RouterDef<i
117
117
  * transport: httpTransport({ url: '/api/lens' }),
118
118
  * });
119
119
  *
120
+ * // Vanilla JS (anywhere)
121
+ * const user = await client.user.get({ input: { id } });
122
+ *
120
123
  * // Component usage
121
124
  * function UserProfile(props: { id: string }) {
122
- * const { data, loading, error } = client.user.get({
125
+ * const { data, loading, error } = client.user.get.createQuery({
123
126
  * input: { id: props.id },
124
- * select: { name: true },
125
127
  * });
126
128
  *
127
- * const { mutate, loading: saving } = client.user.update({
129
+ * const { mutate, loading: saving } = client.user.update.createMutation({
128
130
  * onSuccess: () => console.log('Updated!'),
129
131
  * });
130
132
  *
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -15,14 +15,16 @@
15
15
  * transport: httpTransport({ url: '/api/lens' }),
16
16
  * });
17
17
  *
18
- * // Component usage
19
- * const { data, loading } = client.user.get({ input: { id } });
18
+ * // Vanilla JS (anywhere - SSR, utilities, event handlers)
19
+ * const user = await client.user.get({ input: { id } });
20
+ * client.user.get({ input: { id } }).subscribe(data => console.log(data));
20
21
  *
21
- * // SSR usage
22
- * const user = await client.user.get.fetch({ input: { id } });
22
+ * // SolidJS primitives (in components)
23
+ * const { data, loading } = client.user.get.createQuery({ input: { id } });
24
+ * const { mutate } = client.user.create.createMutation();
23
25
  * ```
24
26
  */
25
- export { createClient, type MutationEndpoint, type MutationHookOptions, type MutationHookResult, type QueryEndpoint, type QueryHookOptions, type QueryHookResult, type TypedClient, } from "./create.js";
27
+ export { createClient, type MutationEndpoint, type MutationPrimitiveOptions, type MutationPrimitiveResult, type QueryEndpoint, type QueryPrimitiveOptions, type QueryPrimitiveResult, type TypedClient, } from "./create.js";
26
28
  export { LensProvider, type LensProviderProps, useLensClient } from "./context.js";
27
29
  export { type CreateLazyQueryResult, type CreateMutationResult, type CreateQueryOptions, type CreateQueryResult, createLazyQuery, createMutation, createQuery, type MutationFn, type QueryInput, } from "./primitives.js";
28
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,OAAO,EACN,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,WAAW,GAChB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMnF,OAAO,EACN,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,eAAe,EAEf,cAAc,EAEd,WAAW,EACX,KAAK,UAAU,EAEf,KAAK,UAAU,GACf,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH,OAAO,EACN,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,WAAW,GAChB,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMnF,OAAO,EACN,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,eAAe,EAEf,cAAc,EAEd,WAAW,EACX,KAAK,UAAU,EAEf,KAAK,UAAU,GACf,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1051,17 +1051,9 @@ class SubscriptionRegistry {
1051
1051
  }
1052
1052
 
1053
1053
  // src/create.ts
1054
- import { createEffect, createSignal, onCleanup } from "solid-js";
1055
- function createQueryHook(baseClient, path) {
1056
- const getEndpoint = (p) => {
1057
- const parts = p.split(".");
1058
- let current = baseClient;
1059
- for (const part of parts) {
1060
- current = current[part];
1061
- }
1062
- return current;
1063
- };
1064
- const useQueryPrimitive = (options) => {
1054
+ import { createSignal, onCleanup } from "solid-js";
1055
+ function createQueryPrimitiveFactory(getEndpoint) {
1056
+ return function createQuery(options) {
1065
1057
  const [data, setData] = createSignal(null);
1066
1058
  const [loading, setLoading] = createSignal(!options?.skip);
1067
1059
  const [error, setError] = createSignal(null);
@@ -1077,7 +1069,7 @@ function createQueryHook(baseClient, path) {
1077
1069
  setError(null);
1078
1070
  return;
1079
1071
  }
1080
- const endpoint = getEndpoint(path);
1072
+ const endpoint = getEndpoint();
1081
1073
  const query = endpoint({ input: options?.input, select: options?.select });
1082
1074
  setLoading(true);
1083
1075
  setError(null);
@@ -1097,10 +1089,6 @@ function createQueryHook(baseClient, path) {
1097
1089
  });
1098
1090
  };
1099
1091
  executeQuery();
1100
- createEffect(() => {
1101
- const _ = JSON.stringify(options);
1102
- executeQuery();
1103
- });
1104
1092
  onCleanup(() => {
1105
1093
  if (unsubscribe) {
1106
1094
  unsubscribe();
@@ -1114,7 +1102,7 @@ function createQueryHook(baseClient, path) {
1114
1102
  }
1115
1103
  setLoading(true);
1116
1104
  setError(null);
1117
- const endpoint = getEndpoint(path);
1105
+ const endpoint = getEndpoint();
1118
1106
  const query = endpoint({ input: options?.input, select: options?.select });
1119
1107
  if (query) {
1120
1108
  unsubscribe = query.subscribe((value) => {
@@ -1134,24 +1122,9 @@ function createQueryHook(baseClient, path) {
1134
1122
  };
1135
1123
  return { data, loading, error, refetch };
1136
1124
  };
1137
- const fetch2 = async (options) => {
1138
- const endpoint = getEndpoint(path);
1139
- const queryResult = endpoint({ input: options?.input, select: options?.select });
1140
- return queryResult.then((data) => data);
1141
- };
1142
- useQueryPrimitive.fetch = fetch2;
1143
- return useQueryPrimitive;
1144
1125
  }
1145
- function createMutationHook(baseClient, path) {
1146
- const getEndpoint = (p) => {
1147
- const parts = p.split(".");
1148
- let current = baseClient;
1149
- for (const part of parts) {
1150
- current = current[part];
1151
- }
1152
- return current;
1153
- };
1154
- const useMutationPrimitive = (hookOptions) => {
1126
+ function createMutationPrimitiveFactory(getEndpoint) {
1127
+ return function createMutation(primitiveOptions) {
1155
1128
  const [data, setData] = createSignal(null);
1156
1129
  const [loading, setLoading] = createSignal(false);
1157
1130
  const [error, setError] = createSignal(null);
@@ -1159,20 +1132,19 @@ function createMutationHook(baseClient, path) {
1159
1132
  setLoading(true);
1160
1133
  setError(null);
1161
1134
  try {
1162
- const endpoint = getEndpoint(path);
1135
+ const endpoint = getEndpoint();
1163
1136
  const result = await endpoint({ input: options.input, select: options.select });
1164
- const mutationResult = result;
1165
- setData(() => mutationResult.data);
1137
+ setData(() => result.data);
1166
1138
  setLoading(false);
1167
- hookOptions?.onSuccess?.(mutationResult.data);
1168
- hookOptions?.onSettled?.();
1169
- return mutationResult.data;
1139
+ primitiveOptions?.onSuccess?.(result.data);
1140
+ primitiveOptions?.onSettled?.();
1141
+ return result.data;
1170
1142
  } catch (err) {
1171
1143
  const mutationError = err instanceof Error ? err : new Error(String(err));
1172
1144
  setError(mutationError);
1173
1145
  setLoading(false);
1174
- hookOptions?.onError?.(mutationError);
1175
- hookOptions?.onSettled?.();
1146
+ primitiveOptions?.onError?.(mutationError);
1147
+ primitiveOptions?.onSettled?.();
1176
1148
  throw mutationError;
1177
1149
  }
1178
1150
  };
@@ -1183,16 +1155,8 @@ function createMutationHook(baseClient, path) {
1183
1155
  };
1184
1156
  return { mutate, loading, error, data, reset };
1185
1157
  };
1186
- const fetch2 = async (options) => {
1187
- const endpoint = getEndpoint(path);
1188
- const result = await endpoint({ input: options.input, select: options.select });
1189
- const mutationResult = result;
1190
- return mutationResult.data;
1191
- };
1192
- useMutationPrimitive.fetch = fetch2;
1193
- return useMutationPrimitive;
1194
1158
  }
1195
- var hookCache = new Map;
1159
+ var primitiveCache = new Map;
1196
1160
  function createClient2(config) {
1197
1161
  const baseClient = createClient(config);
1198
1162
  function createProxy(path) {
@@ -1201,21 +1165,35 @@ function createClient2(config) {
1201
1165
  if (typeof prop === "symbol")
1202
1166
  return;
1203
1167
  const key = prop;
1204
- if (key === "fetch") {
1205
- return async (options) => {
1206
- const parts = path.split(".");
1207
- let current = baseClient;
1208
- for (const part of parts) {
1209
- current = current[part];
1210
- }
1211
- const endpointFn = current;
1212
- const queryResult = endpointFn(options);
1213
- const result = await queryResult;
1214
- if (result && typeof result === "object" && "data" in result && Object.keys(result).length === 1) {
1215
- return result.data;
1216
- }
1217
- return result;
1218
- };
1168
+ if (key === "createQuery") {
1169
+ const cacheKey = `${path}:createQuery`;
1170
+ if (!primitiveCache.has(cacheKey)) {
1171
+ const getEndpoint = () => {
1172
+ const parts = path.split(".");
1173
+ let current = baseClient;
1174
+ for (const part of parts) {
1175
+ current = current[part];
1176
+ }
1177
+ return current;
1178
+ };
1179
+ primitiveCache.set(cacheKey, createQueryPrimitiveFactory(getEndpoint));
1180
+ }
1181
+ return primitiveCache.get(cacheKey);
1182
+ }
1183
+ if (key === "createMutation") {
1184
+ const cacheKey = `${path}:createMutation`;
1185
+ if (!primitiveCache.has(cacheKey)) {
1186
+ const getEndpoint = () => {
1187
+ const parts = path.split(".");
1188
+ let current = baseClient;
1189
+ for (const part of parts) {
1190
+ current = current[part];
1191
+ }
1192
+ return current;
1193
+ };
1194
+ primitiveCache.set(cacheKey, createMutationPrimitiveFactory(getEndpoint));
1195
+ }
1196
+ return primitiveCache.get(cacheKey);
1219
1197
  }
1220
1198
  if (key === "then")
1221
1199
  return;
@@ -1225,33 +1203,17 @@ function createClient2(config) {
1225
1203
  return createProxy(newPath);
1226
1204
  },
1227
1205
  apply(_target, _thisArg, args) {
1228
- const options = args[0];
1229
- const isQueryOptions = options && (("input" in options) || ("select" in options) || ("skip" in options));
1230
- const isMutationOptions = !options || !isQueryOptions && (Object.keys(options).length === 0 || ("onSuccess" in options) || ("onError" in options) || ("onSettled" in options));
1231
- const cacheKeyQuery = `${path}:query`;
1232
- const cacheKeyMutation = `${path}:mutation`;
1233
- if (isQueryOptions) {
1234
- if (!hookCache.has(cacheKeyQuery)) {
1235
- hookCache.set(cacheKeyQuery, createQueryHook(baseClient, path));
1236
- }
1237
- const hook2 = hookCache.get(cacheKeyQuery);
1238
- return hook2(options);
1239
- }
1240
- if (isMutationOptions) {
1241
- if (!hookCache.has(cacheKeyMutation)) {
1242
- hookCache.set(cacheKeyMutation, createMutationHook(baseClient, path));
1243
- }
1244
- const hook2 = hookCache.get(cacheKeyMutation);
1245
- return hook2(options);
1246
- }
1247
- if (!hookCache.has(cacheKeyQuery)) {
1248
- hookCache.set(cacheKeyQuery, createQueryHook(baseClient, path));
1206
+ const parts = path.split(".");
1207
+ let current = baseClient;
1208
+ for (const part of parts) {
1209
+ current = current[part];
1249
1210
  }
1250
- const hook = hookCache.get(cacheKeyQuery);
1251
- return hook(options);
1211
+ const endpoint = current;
1212
+ return endpoint(args[0]);
1252
1213
  }
1253
1214
  };
1254
- return new Proxy(() => {}, handler);
1215
+ const proxy = new Proxy(() => {}, handler);
1216
+ return proxy;
1255
1217
  }
1256
1218
  return createProxy("");
1257
1219
  }
@@ -1271,7 +1233,7 @@ function useLensClient() {
1271
1233
  return client;
1272
1234
  }
1273
1235
  // src/primitives.ts
1274
- import { createEffect as createEffect2, createSignal as createSignal2, onCleanup as onCleanup2 } from "solid-js";
1236
+ import { createEffect, createSignal as createSignal2, onCleanup as onCleanup2 } from "solid-js";
1275
1237
  function resolveQuery(input) {
1276
1238
  return typeof input === "function" ? input() : input;
1277
1239
  }
@@ -1310,7 +1272,7 @@ function createQuery(queryInput, options) {
1310
1272
  };
1311
1273
  const initialQuery = resolveQuery(queryInput);
1312
1274
  executeQuery(initialQuery);
1313
- createEffect2(() => {
1275
+ createEffect(() => {
1314
1276
  const queryResult = resolveQuery(queryInput);
1315
1277
  if (queryResult !== initialQuery) {
1316
1278
  executeQuery(queryResult);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylphx/lens-solid",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "SolidJS bindings for Lens API framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,8 +31,8 @@
31
31
  "author": "SylphxAI",
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
- "@sylphx/lens-client": "^2.2.0",
35
- "@sylphx/lens-core": "^2.1.0"
34
+ "@sylphx/lens-client": "^2.2.1",
35
+ "@sylphx/lens-core": "^2.2.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "solid-js": ">=1.8.0"
package/src/create.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * @sylphx/lens-solid - Create Client
3
3
  *
4
4
  * Creates a typed Lens client with SolidJS primitives.
5
- * Each endpoint can be called directly as a primitive or via .fetch() for promises.
5
+ * Base client methods work in vanilla JS, primitives are extensions.
6
6
  *
7
7
  * @example
8
8
  * ```tsx
@@ -15,11 +15,13 @@
15
15
  * transport: httpTransport({ url: '/api/lens' }),
16
16
  * });
17
17
  *
18
- * // In component
19
- * const { data, loading } = client.user.get({ input: { id } });
18
+ * // Vanilla JS (anywhere - SSR, utilities, event handlers)
19
+ * const user = await client.user.get({ input: { id } });
20
+ * client.user.get({ input: { id } }).subscribe(data => console.log(data));
20
21
  *
21
- * // In SSR
22
- * const user = await client.user.get.fetch({ input: { id } });
22
+ * // SolidJS primitives (in components)
23
+ * const { data, loading } = client.user.get.createQuery({ input: { id } });
24
+ * const { mutate, loading } = client.user.create.createMutation();
23
25
  * ```
24
26
  */
25
27
 
@@ -31,14 +33,14 @@ import {
31
33
  type TypedClientConfig,
32
34
  } from "@sylphx/lens-client";
33
35
  import type { MutationDef, QueryDef, RouterDef, RouterRoutes } from "@sylphx/lens-core";
34
- import { type Accessor, createEffect, createSignal, onCleanup } from "solid-js";
36
+ import { type Accessor, createSignal, onCleanup } from "solid-js";
35
37
 
36
38
  // =============================================================================
37
39
  // Types
38
40
  // =============================================================================
39
41
 
40
- /** Query hook options */
41
- export interface QueryHookOptions<TInput> {
42
+ /** Query primitive options */
43
+ export interface QueryPrimitiveOptions<TInput> {
42
44
  /** Query input parameters */
43
45
  input?: TInput;
44
46
  /** Field selection */
@@ -47,8 +49,8 @@ export interface QueryHookOptions<TInput> {
47
49
  skip?: boolean;
48
50
  }
49
51
 
50
- /** Query hook result */
51
- export interface QueryHookResult<T> {
52
+ /** Query primitive result */
53
+ export interface QueryPrimitiveResult<T> {
52
54
  /** Reactive data accessor */
53
55
  data: Accessor<T | null>;
54
56
  /** Reactive loading state */
@@ -59,8 +61,8 @@ export interface QueryHookResult<T> {
59
61
  refetch: () => void;
60
62
  }
61
63
 
62
- /** Mutation hook options */
63
- export interface MutationHookOptions<TOutput> {
64
+ /** Mutation primitive options */
65
+ export interface MutationPrimitiveOptions<TOutput> {
64
66
  /** Called on successful mutation */
65
67
  onSuccess?: (data: TOutput) => void;
66
68
  /** Called on mutation error */
@@ -69,8 +71,8 @@ export interface MutationHookOptions<TOutput> {
69
71
  onSettled?: () => void;
70
72
  }
71
73
 
72
- /** Mutation hook result */
73
- export interface MutationHookResult<TInput, TOutput> {
74
+ /** Mutation primitive result */
75
+ export interface MutationPrimitiveResult<TInput, TOutput> {
74
76
  /** Execute the mutation */
75
77
  mutate: (options: { input: TInput; select?: SelectionObject }) => Promise<TOutput>;
76
78
  /** Reactive loading state */
@@ -83,31 +85,28 @@ export interface MutationHookResult<TInput, TOutput> {
83
85
  reset: () => void;
84
86
  }
85
87
 
86
- /** Query endpoint type */
88
+ /** Query endpoint with SolidJS primitives */
87
89
  export interface QueryEndpoint<TInput, TOutput> {
88
- /** Primitive call (in component) */
89
- <_TSelect extends SelectionObject = Record<string, never>>(
90
- options: TInput extends void ? QueryHookOptions<void> | void : QueryHookOptions<TInput>,
91
- ): QueryHookResult<TOutput>;
92
-
93
- /** Promise call (SSR) */
94
- fetch: <TSelect extends SelectionObject = Record<string, never>>(
95
- options: TInput extends void
96
- ? { input?: void; select?: TSelect } | void
97
- : { input: TInput; select?: TSelect },
98
- ) => Promise<TOutput>;
90
+ /** Vanilla JS call - returns QueryResult (Promise + Observable) */
91
+ (options?: { input?: TInput; select?: SelectionObject }): QueryResult<TOutput>;
92
+
93
+ /** SolidJS primitive for reactive queries */
94
+ createQuery: (
95
+ options?: TInput extends void
96
+ ? QueryPrimitiveOptions<void> | void
97
+ : QueryPrimitiveOptions<TInput>,
98
+ ) => QueryPrimitiveResult<TOutput>;
99
99
  }
100
100
 
101
- /** Mutation endpoint type */
101
+ /** Mutation endpoint with SolidJS primitives */
102
102
  export interface MutationEndpoint<TInput, TOutput> {
103
- /** Primitive call (in component) */
104
- (options?: MutationHookOptions<TOutput>): MutationHookResult<TInput, TOutput>;
105
-
106
- /** Promise call (SSR) */
107
- fetch: <TSelect extends SelectionObject = Record<string, never>>(options: {
108
- input: TInput;
109
- select?: TSelect;
110
- }) => Promise<TOutput>;
103
+ /** Vanilla JS call - returns Promise */
104
+ (options: { input: TInput; select?: SelectionObject }): Promise<{ data: TOutput }>;
105
+
106
+ /** SolidJS primitive for mutations */
107
+ createMutation: (
108
+ options?: MutationPrimitiveOptions<TOutput>,
109
+ ) => MutationPrimitiveResult<TInput, TOutput>;
111
110
  }
112
111
 
113
112
  /** Infer client type from router routes */
@@ -126,26 +125,18 @@ export type TypedClient<TRouter extends RouterDef> =
126
125
  TRouter extends RouterDef<infer TRoutes> ? InferTypedClient<TRoutes> : never;
127
126
 
128
127
  // =============================================================================
129
- // Hook Factories
128
+ // Primitive Factories
130
129
  // =============================================================================
131
130
 
132
131
  /**
133
- * Create a query primitive for a specific endpoint
132
+ * Create createQuery primitive for a specific endpoint
134
133
  */
135
- function createQueryHook<TInput, TOutput>(
136
- baseClient: unknown,
137
- path: string,
138
- ): QueryEndpoint<TInput, TOutput> {
139
- const getEndpoint = (p: string) => {
140
- const parts = p.split(".");
141
- let current: unknown = baseClient;
142
- for (const part of parts) {
143
- current = (current as Record<string, unknown>)[part];
144
- }
145
- return current as (options: unknown) => QueryResult<TOutput>;
146
- };
147
-
148
- const useQueryPrimitive = (options?: QueryHookOptions<TInput>): QueryHookResult<TOutput> => {
134
+ function createQueryPrimitiveFactory<TInput, TOutput>(
135
+ getEndpoint: () => (options: unknown) => QueryResult<TOutput>,
136
+ ) {
137
+ return function createQuery(
138
+ options?: QueryPrimitiveOptions<TInput>,
139
+ ): QueryPrimitiveResult<TOutput> {
149
140
  const [data, setData] = createSignal<TOutput | null>(null);
150
141
  const [loading, setLoading] = createSignal(!options?.skip);
151
142
  const [error, setError] = createSignal<Error | null>(null);
@@ -165,7 +156,7 @@ function createQueryHook<TInput, TOutput>(
165
156
  return;
166
157
  }
167
158
 
168
- const endpoint = getEndpoint(path);
159
+ const endpoint = getEndpoint();
169
160
  const query = endpoint({ input: options?.input, select: options?.select });
170
161
 
171
162
  setLoading(true);
@@ -191,16 +182,9 @@ function createQueryHook<TInput, TOutput>(
191
182
  );
192
183
  };
193
184
 
194
- // Execute initial query synchronously
185
+ // Execute initial query
195
186
  executeQuery();
196
187
 
197
- // Use createEffect for reactive updates when options change
198
- createEffect(() => {
199
- // Access options to track them (Solid will re-run when they change)
200
- const _ = JSON.stringify(options);
201
- executeQuery();
202
- });
203
-
204
188
  onCleanup(() => {
205
189
  if (unsubscribe) {
206
190
  unsubscribe();
@@ -215,7 +199,7 @@ function createQueryHook<TInput, TOutput>(
215
199
  }
216
200
  setLoading(true);
217
201
  setError(null);
218
- const endpoint = getEndpoint(path);
202
+ const endpoint = getEndpoint();
219
203
  const query = endpoint({ input: options?.input, select: options?.select });
220
204
  if (query) {
221
205
  unsubscribe = query.subscribe((value) => {
@@ -239,42 +223,17 @@ function createQueryHook<TInput, TOutput>(
239
223
 
240
224
  return { data, loading, error, refetch };
241
225
  };
242
-
243
- // Fetch method for promises (SSR)
244
- const fetch = async (options?: {
245
- input?: TInput;
246
- select?: SelectionObject;
247
- }): Promise<TOutput> => {
248
- const endpoint = getEndpoint(path);
249
- const queryResult = endpoint({ input: options?.input, select: options?.select });
250
- return queryResult.then((data) => data);
251
- };
252
-
253
- // Attach fetch method to the hook function
254
- useQueryPrimitive.fetch = fetch;
255
-
256
- return useQueryPrimitive as unknown as QueryEndpoint<TInput, TOutput>;
257
226
  }
258
227
 
259
228
  /**
260
- * Create a mutation primitive for a specific endpoint
229
+ * Create createMutation primitive for a specific endpoint
261
230
  */
262
- function createMutationHook<TInput, TOutput>(
263
- baseClient: unknown,
264
- path: string,
265
- ): MutationEndpoint<TInput, TOutput> {
266
- const getEndpoint = (p: string) => {
267
- const parts = p.split(".");
268
- let current: unknown = baseClient;
269
- for (const part of parts) {
270
- current = (current as Record<string, unknown>)[part];
271
- }
272
- return current as (options: unknown) => QueryResult<{ data: TOutput }>;
273
- };
274
-
275
- const useMutationPrimitive = (
276
- hookOptions?: MutationHookOptions<TOutput>,
277
- ): MutationHookResult<TInput, TOutput> => {
231
+ function createMutationPrimitiveFactory<TInput, TOutput>(
232
+ getEndpoint: () => (options: unknown) => Promise<{ data: TOutput }>,
233
+ ) {
234
+ return function createMutation(
235
+ primitiveOptions?: MutationPrimitiveOptions<TOutput>,
236
+ ): MutationPrimitiveResult<TInput, TOutput> {
278
237
  const [data, setData] = createSignal<TOutput | null>(null);
279
238
  const [loading, setLoading] = createSignal(false);
280
239
  const [error, setError] = createSignal<Error | null>(null);
@@ -287,24 +246,23 @@ function createMutationHook<TInput, TOutput>(
287
246
  setError(null);
288
247
 
289
248
  try {
290
- const endpoint = getEndpoint(path);
249
+ const endpoint = getEndpoint();
291
250
  const result = await endpoint({ input: options.input, select: options.select });
292
- const mutationResult = result as unknown as { data: TOutput };
293
251
 
294
- setData(() => mutationResult.data);
252
+ setData(() => result.data);
295
253
  setLoading(false);
296
254
 
297
- hookOptions?.onSuccess?.(mutationResult.data);
298
- hookOptions?.onSettled?.();
255
+ primitiveOptions?.onSuccess?.(result.data);
256
+ primitiveOptions?.onSettled?.();
299
257
 
300
- return mutationResult.data;
258
+ return result.data;
301
259
  } catch (err) {
302
260
  const mutationError = err instanceof Error ? err : new Error(String(err));
303
261
  setError(mutationError);
304
262
  setLoading(false);
305
263
 
306
- hookOptions?.onError?.(mutationError);
307
- hookOptions?.onSettled?.();
264
+ primitiveOptions?.onError?.(mutationError);
265
+ primitiveOptions?.onSettled?.();
308
266
 
309
267
  throw mutationError;
310
268
  }
@@ -318,34 +276,20 @@ function createMutationHook<TInput, TOutput>(
318
276
 
319
277
  return { mutate, loading, error, data, reset };
320
278
  };
321
-
322
- // Fetch method for promises (SSR)
323
- const fetch = async (options: { input: TInput; select?: SelectionObject }): Promise<TOutput> => {
324
- const endpoint = getEndpoint(path);
325
- const result = await endpoint({ input: options.input, select: options.select });
326
- const mutationResult = result as unknown as { data: TOutput };
327
- return mutationResult.data;
328
- };
329
-
330
- // Attach fetch method to the hook function
331
- useMutationPrimitive.fetch = fetch;
332
-
333
- return useMutationPrimitive as unknown as MutationEndpoint<TInput, TOutput>;
334
279
  }
335
280
 
336
281
  // =============================================================================
337
282
  // Create Client
338
283
  // =============================================================================
339
284
 
340
- // Cache for hook functions
341
- const hookCache = new Map<string, unknown>();
285
+ // Cache for primitive functions to ensure stable references
286
+ const primitiveCache = new Map<string, unknown>();
342
287
 
343
288
  /**
344
289
  * Create a Lens client with SolidJS primitives.
345
290
  *
346
- * Each endpoint can be called:
347
- * - Directly as a primitive: `client.user.get({ input: { id } })`
348
- * - Via .fetch() for promises: `await client.user.get.fetch({ input: { id } })`
291
+ * Base client methods work in vanilla JS (SSR, utilities, event handlers).
292
+ * SolidJS primitives are available as `.createQuery()` and `.createMutation()`.
349
293
  *
350
294
  * @example
351
295
  * ```tsx
@@ -358,14 +302,16 @@ const hookCache = new Map<string, unknown>();
358
302
  * transport: httpTransport({ url: '/api/lens' }),
359
303
  * });
360
304
  *
305
+ * // Vanilla JS (anywhere)
306
+ * const user = await client.user.get({ input: { id } });
307
+ *
361
308
  * // Component usage
362
309
  * function UserProfile(props: { id: string }) {
363
- * const { data, loading, error } = client.user.get({
310
+ * const { data, loading, error } = client.user.get.createQuery({
364
311
  * input: { id: props.id },
365
- * select: { name: true },
366
312
  * });
367
313
  *
368
- * const { mutate, loading: saving } = client.user.update({
314
+ * const { mutate, loading: saving } = client.user.update.createMutation({
369
315
  * onSuccess: () => console.log('Updated!'),
370
316
  * });
371
317
  *
@@ -386,6 +332,7 @@ const hookCache = new Map<string, unknown>();
386
332
  export function createClient<TRouter extends RouterDef>(
387
333
  config: LensClientConfig | TypedClientConfig<{ router: TRouter }>,
388
334
  ): TypedClient<TRouter> {
335
+ // Create base client for transport
389
336
  const baseClient = createBaseClient(config as LensClientConfig);
390
337
 
391
338
  function createProxy(path: string): unknown {
@@ -394,27 +341,38 @@ export function createClient<TRouter extends RouterDef>(
394
341
  if (typeof prop === "symbol") return undefined;
395
342
  const key = prop as string;
396
343
 
397
- if (key === "fetch") {
398
- return async (options: unknown) => {
399
- const parts = path.split(".");
400
- let current: unknown = baseClient;
401
- for (const part of parts) {
402
- current = (current as Record<string, unknown>)[part];
403
- }
404
- const endpointFn = current as (opts: unknown) => QueryResult<unknown>;
405
- const queryResult = endpointFn(options);
406
- const result = await queryResult;
407
-
408
- if (
409
- result &&
410
- typeof result === "object" &&
411
- "data" in result &&
412
- Object.keys(result).length === 1
413
- ) {
414
- return (result as { data: unknown }).data;
415
- }
416
- return result;
417
- };
344
+ // Handle .createQuery() - SolidJS primitive for queries
345
+ if (key === "createQuery") {
346
+ const cacheKey = `${path}:createQuery`;
347
+ if (!primitiveCache.has(cacheKey)) {
348
+ const getEndpoint = () => {
349
+ const parts = path.split(".");
350
+ let current: unknown = baseClient;
351
+ for (const part of parts) {
352
+ current = (current as Record<string, unknown>)[part];
353
+ }
354
+ return current as (options: unknown) => QueryResult<unknown>;
355
+ };
356
+ primitiveCache.set(cacheKey, createQueryPrimitiveFactory(getEndpoint));
357
+ }
358
+ return primitiveCache.get(cacheKey);
359
+ }
360
+
361
+ // Handle .createMutation() - SolidJS primitive for mutations
362
+ if (key === "createMutation") {
363
+ const cacheKey = `${path}:createMutation`;
364
+ if (!primitiveCache.has(cacheKey)) {
365
+ const getEndpoint = () => {
366
+ const parts = path.split(".");
367
+ let current: unknown = baseClient;
368
+ for (const part of parts) {
369
+ current = (current as Record<string, unknown>)[part];
370
+ }
371
+ return current as (options: unknown) => Promise<{ data: unknown }>;
372
+ };
373
+ primitiveCache.set(cacheKey, createMutationPrimitiveFactory(getEndpoint));
374
+ }
375
+ return primitiveCache.get(cacheKey);
418
376
  }
419
377
 
420
378
  if (key === "then") return undefined;
@@ -425,47 +383,19 @@ export function createClient<TRouter extends RouterDef>(
425
383
  },
426
384
 
427
385
  apply(_target, _thisArg, args) {
428
- const options = args[0] as Record<string, unknown> | undefined;
429
-
430
- const isQueryOptions =
431
- options && ("input" in options || "select" in options || "skip" in options);
432
-
433
- const isMutationOptions =
434
- !options ||
435
- (!isQueryOptions &&
436
- (Object.keys(options).length === 0 ||
437
- "onSuccess" in options ||
438
- "onError" in options ||
439
- "onSettled" in options));
440
-
441
- const cacheKeyQuery = `${path}:query`;
442
- const cacheKeyMutation = `${path}:mutation`;
443
-
444
- if (isQueryOptions) {
445
- if (!hookCache.has(cacheKeyQuery)) {
446
- hookCache.set(cacheKeyQuery, createQueryHook(baseClient, path));
447
- }
448
- const hook = hookCache.get(cacheKeyQuery) as (opts: unknown) => unknown;
449
- return hook(options);
450
- }
451
-
452
- if (isMutationOptions) {
453
- if (!hookCache.has(cacheKeyMutation)) {
454
- hookCache.set(cacheKeyMutation, createMutationHook(baseClient, path));
455
- }
456
- const hook = hookCache.get(cacheKeyMutation) as (opts: unknown) => unknown;
457
- return hook(options);
458
- }
459
-
460
- if (!hookCache.has(cacheKeyQuery)) {
461
- hookCache.set(cacheKeyQuery, createQueryHook(baseClient, path));
386
+ // Direct call - delegate to base client (returns QueryResult or Promise)
387
+ const parts = path.split(".");
388
+ let current: unknown = baseClient;
389
+ for (const part of parts) {
390
+ current = (current as Record<string, unknown>)[part];
462
391
  }
463
- const hook = hookCache.get(cacheKeyQuery) as (opts: unknown) => unknown;
464
- return hook(options);
392
+ const endpoint = current as (options: unknown) => unknown;
393
+ return endpoint(args[0]);
465
394
  },
466
395
  };
467
396
 
468
- return new Proxy((() => {}) as (...args: unknown[]) => unknown, handler);
397
+ const proxy = new Proxy((() => {}) as (...args: unknown[]) => unknown, handler);
398
+ return proxy;
469
399
  }
470
400
 
471
401
  return createProxy("") as TypedClient<TRouter>;
package/src/index.ts CHANGED
@@ -15,11 +15,13 @@
15
15
  * transport: httpTransport({ url: '/api/lens' }),
16
16
  * });
17
17
  *
18
- * // Component usage
19
- * const { data, loading } = client.user.get({ input: { id } });
18
+ * // Vanilla JS (anywhere - SSR, utilities, event handlers)
19
+ * const user = await client.user.get({ input: { id } });
20
+ * client.user.get({ input: { id } }).subscribe(data => console.log(data));
20
21
  *
21
- * // SSR usage
22
- * const user = await client.user.get.fetch({ input: { id } });
22
+ * // SolidJS primitives (in components)
23
+ * const { data, loading } = client.user.get.createQuery({ input: { id } });
24
+ * const { mutate } = client.user.create.createMutation();
23
25
  * ```
24
26
  */
25
27
 
@@ -30,11 +32,11 @@
30
32
  export {
31
33
  createClient,
32
34
  type MutationEndpoint,
33
- type MutationHookOptions,
34
- type MutationHookResult,
35
+ type MutationPrimitiveOptions,
36
+ type MutationPrimitiveResult,
35
37
  type QueryEndpoint,
36
- type QueryHookOptions,
37
- type QueryHookResult,
38
+ type QueryPrimitiveOptions,
39
+ type QueryPrimitiveResult,
38
40
  type TypedClient,
39
41
  } from "./create.js";
40
42