atmx-react 0.44.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +135 -0
- package/dist/index.d.ts +135 -0
- package/dist/index.js +628 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +602 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +5 -2
- package/src/components/AxGet.tsx +0 -19
- package/src/components/AxMutation.tsx +0 -48
- package/src/components/AxQuery.tsx +0 -41
- package/src/components/AxTrigger.tsx +0 -36
- package/src/components/AxWhen.tsx +0 -54
- package/src/context/AxiomDataContext.tsx +0 -27
- package/src/context/AxiomProvider.tsx +0 -97
- package/src/core/ActiveQuery.ts +0 -217
- package/src/core/QueryManager.ts +0 -40
- package/src/hooks/useAxiom.ts +0 -13
- package/src/hooks/useAxiomMutation.ts +0 -236
- package/src/hooks/useAxiomQuery.ts +0 -41
- package/src/index.ts +0 -39
- package/src/utils/core-bridge.ts +0 -62
- package/tsconfig.json +0 -27
- package/tsup.config.ts +0 -11
package/dist/index.js
ADDED
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
|
+
|
|
22
|
+
// src/index.ts
|
|
23
|
+
var index_exports = {};
|
|
24
|
+
__export(index_exports, {
|
|
25
|
+
AxQuery: () => AxQuery,
|
|
26
|
+
AxTrigger: () => AxTrigger,
|
|
27
|
+
AxWhen: () => AxWhen,
|
|
28
|
+
AxiomContext: () => AxiomContext,
|
|
29
|
+
AxiomDataContext: () => AxiomDataContext,
|
|
30
|
+
AxiomProvider: () => AxiomProvider,
|
|
31
|
+
axiomQueryManager: () => axiomQueryManager,
|
|
32
|
+
clearAuthToken: () => import_atmx_web.clearAuthToken,
|
|
33
|
+
setAuthToken: () => import_atmx_web.setAuthToken,
|
|
34
|
+
useAxiom: () => useAxiom,
|
|
35
|
+
useAxiomContext: () => useAxiomContext,
|
|
36
|
+
useAxiomData: () => useAxiomData,
|
|
37
|
+
useAxiomMutation: () => useAxiomMutation,
|
|
38
|
+
useAxiomQuery: () => useAxiomQuery
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(index_exports);
|
|
41
|
+
|
|
42
|
+
// src/utils/core-bridge.ts
|
|
43
|
+
var import_atmx_web = require("atmx-web");
|
|
44
|
+
var import_atmx_web2 = require("atmx-web");
|
|
45
|
+
var import_atmx_web3 = require("atmx-web");
|
|
46
|
+
var globalReqCounter = 0;
|
|
47
|
+
var getNextReqId = () => ++globalReqCounter;
|
|
48
|
+
|
|
49
|
+
// src/context/AxiomProvider.tsx
|
|
50
|
+
var import_react = require("react");
|
|
51
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
52
|
+
var AxiomContext = (0, import_react.createContext)(
|
|
53
|
+
void 0
|
|
54
|
+
);
|
|
55
|
+
var AxiomProvider = ({
|
|
56
|
+
configUrl,
|
|
57
|
+
config,
|
|
58
|
+
children,
|
|
59
|
+
fallback
|
|
60
|
+
}) => {
|
|
61
|
+
const [state, setState] = (0, import_react.useState)({
|
|
62
|
+
isReady: false,
|
|
63
|
+
error: null,
|
|
64
|
+
config: null
|
|
65
|
+
});
|
|
66
|
+
const initStarted = (0, import_react.useRef)(false);
|
|
67
|
+
(0, import_react.useEffect)(() => {
|
|
68
|
+
if (initStarted.current) return;
|
|
69
|
+
initStarted.current = true;
|
|
70
|
+
const bootSequence = async () => {
|
|
71
|
+
try {
|
|
72
|
+
let finalConfig;
|
|
73
|
+
if (configUrl) {
|
|
74
|
+
const res = await fetch(configUrl);
|
|
75
|
+
if (!res.ok)
|
|
76
|
+
throw new Error(`Failed to load config from ${configUrl}`);
|
|
77
|
+
finalConfig = await res.json();
|
|
78
|
+
} else if (config) {
|
|
79
|
+
finalConfig = config;
|
|
80
|
+
} else {
|
|
81
|
+
throw new Error(
|
|
82
|
+
"AxiomProvider requires either 'configUrl' or 'config' prop."
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (!finalConfig.contracts || Object.keys(finalConfig.contracts).length === 0) {
|
|
86
|
+
throw new Error("No contracts defined in ATMX config.");
|
|
87
|
+
}
|
|
88
|
+
await (0, import_atmx_web.initWasm)(finalConfig);
|
|
89
|
+
console.log(`\u269B\uFE0F ATMX-React: Provider ready.`);
|
|
90
|
+
setState({ isReady: true, error: null, config: finalConfig });
|
|
91
|
+
} catch (err) {
|
|
92
|
+
console.error("ATMX Provider Boot Error:", err);
|
|
93
|
+
setState({ isReady: false, error: err, config: null });
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
bootSequence();
|
|
97
|
+
}, [configUrl, config]);
|
|
98
|
+
if (state.error)
|
|
99
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { color: "red", padding: "20px", fontFamily: "monospace" }, children: [
|
|
100
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "ATMX Initialization Failed:" }),
|
|
101
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
|
|
102
|
+
state.error.message
|
|
103
|
+
] });
|
|
104
|
+
if (!state.isReady) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: fallback || null });
|
|
105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AxiomContext.Provider, { value: state, children });
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/context/AxiomDataContext.tsx
|
|
109
|
+
var import_react2 = require("react");
|
|
110
|
+
var AxiomDataContext = (0, import_react2.createContext)(null);
|
|
111
|
+
function useAxiomContext() {
|
|
112
|
+
const context = (0, import_react2.useContext)(AxiomDataContext);
|
|
113
|
+
if (!context) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
"useAxiomContext must be used within an <AxQuery> or <AxMutate> scope."
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return context;
|
|
119
|
+
}
|
|
120
|
+
function useAxiomData() {
|
|
121
|
+
const context = (0, import_react2.useContext)(AxiomDataContext);
|
|
122
|
+
return context?.data || {};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/hooks/useAxiomQuery.ts
|
|
126
|
+
var import_react4 = require("react");
|
|
127
|
+
|
|
128
|
+
// src/hooks/useAxiom.ts
|
|
129
|
+
var import_react3 = require("react");
|
|
130
|
+
var useAxiom = () => {
|
|
131
|
+
const context = (0, import_react3.useContext)(AxiomContext);
|
|
132
|
+
if (context === void 0) {
|
|
133
|
+
throw new Error("useAxiom must be used within an <AxiomProvider>. Did you forget to wrap your app?");
|
|
134
|
+
}
|
|
135
|
+
return context;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// src/core/ActiveQuery.ts
|
|
139
|
+
var ActiveQuery = class {
|
|
140
|
+
constructor(queryKey, def) {
|
|
141
|
+
__publicField(this, "queryKey");
|
|
142
|
+
__publicField(this, "def");
|
|
143
|
+
__publicField(this, "state");
|
|
144
|
+
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
145
|
+
__publicField(this, "currentReqId", null);
|
|
146
|
+
this.queryKey = queryKey;
|
|
147
|
+
this.def = def;
|
|
148
|
+
this.state = {
|
|
149
|
+
status: "idle",
|
|
150
|
+
data: null,
|
|
151
|
+
error: null,
|
|
152
|
+
isFetching: false,
|
|
153
|
+
isMutating: false,
|
|
154
|
+
source: null
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
getState() {
|
|
158
|
+
return this.state;
|
|
159
|
+
}
|
|
160
|
+
subscribe(listener) {
|
|
161
|
+
this.listeners.add(listener);
|
|
162
|
+
return () => this.listeners.delete(listener);
|
|
163
|
+
}
|
|
164
|
+
updateState(partial) {
|
|
165
|
+
this.state = { ...this.state, ...partial };
|
|
166
|
+
this.listeners.forEach((l) => l(this.state));
|
|
167
|
+
}
|
|
168
|
+
fetch(force = false, debug = false) {
|
|
169
|
+
if (this.state.isFetching && !force) return;
|
|
170
|
+
this.updateState({
|
|
171
|
+
isFetching: true,
|
|
172
|
+
status: this.state.data ? "success" : "loading"
|
|
173
|
+
});
|
|
174
|
+
const reqId = getNextReqId();
|
|
175
|
+
this.currentReqId = reqId;
|
|
176
|
+
const syntheticRoute = {
|
|
177
|
+
id: this.def.endpointId,
|
|
178
|
+
namespace: this.def.namespace,
|
|
179
|
+
name: this.def.name || "unknown",
|
|
180
|
+
method: this.def.method,
|
|
181
|
+
pathTemplate: this.def.path,
|
|
182
|
+
isStream: !!this.def.isStream
|
|
183
|
+
};
|
|
184
|
+
const { path } = (0, import_atmx_web2.buildRequestPath)(syntheticRoute, this.def.args);
|
|
185
|
+
if (debug) {
|
|
186
|
+
console.groupCollapsed(
|
|
187
|
+
`%c\u2794 WASM QUERY [#${reqId}]`,
|
|
188
|
+
`color: #7c3aed; font-weight: bold;`
|
|
189
|
+
);
|
|
190
|
+
console.log("Namespace:", this.def.namespace);
|
|
191
|
+
console.log("Endpoint ID:", this.def.endpointId);
|
|
192
|
+
console.log("Path:", path);
|
|
193
|
+
console.groupEnd();
|
|
194
|
+
}
|
|
195
|
+
import_atmx_web3.pendingRequests.set(reqId, {
|
|
196
|
+
isStream: !!this.def.isStream,
|
|
197
|
+
onResponse: (response) => {
|
|
198
|
+
if (this.currentReqId !== reqId) return;
|
|
199
|
+
if (debug) {
|
|
200
|
+
const evtName = response.eventType === 1 ? "NetworkSuccess" : response.eventType === 2 ? "CacheHit" : response.eventType === 3 ? "CacheHitAndFetching" : response.eventType === 4 ? "Error" : "Complete";
|
|
201
|
+
console.groupCollapsed(
|
|
202
|
+
`%c\u2190 WASM RESP [#${reqId}]`,
|
|
203
|
+
`color: #059669; font-weight: bold;`
|
|
204
|
+
);
|
|
205
|
+
console.log("Event Type:", evtName);
|
|
206
|
+
if (response.data) console.log("Data:", response.data);
|
|
207
|
+
if (response.error) console.log("Error:", response.error);
|
|
208
|
+
console.groupEnd();
|
|
209
|
+
}
|
|
210
|
+
if (response.eventType === 4) {
|
|
211
|
+
this.updateState({
|
|
212
|
+
status: "error",
|
|
213
|
+
error: response.error || null,
|
|
214
|
+
isFetching: false
|
|
215
|
+
});
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (response.data) {
|
|
219
|
+
try {
|
|
220
|
+
const decodedData = this.def.decoder(response.data);
|
|
221
|
+
let source = "network";
|
|
222
|
+
let isFetching = false;
|
|
223
|
+
if (response.eventType === 2) {
|
|
224
|
+
source = "cache";
|
|
225
|
+
isFetching = false;
|
|
226
|
+
} else if (response.eventType === 3) {
|
|
227
|
+
source = "cache";
|
|
228
|
+
isFetching = true;
|
|
229
|
+
} else if (response.eventType === 1) {
|
|
230
|
+
source = "network";
|
|
231
|
+
isFetching = false;
|
|
232
|
+
}
|
|
233
|
+
this.updateState({
|
|
234
|
+
status: "success",
|
|
235
|
+
data: decodedData,
|
|
236
|
+
error: null,
|
|
237
|
+
isFetching,
|
|
238
|
+
source
|
|
239
|
+
});
|
|
240
|
+
} catch (e) {
|
|
241
|
+
this.updateState({
|
|
242
|
+
status: "error",
|
|
243
|
+
error: { message: "Decoding failed", details: String(e) },
|
|
244
|
+
isFetching: false
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
onComplete: () => {
|
|
250
|
+
if (this.currentReqId !== reqId) return;
|
|
251
|
+
this.updateState({ isFetching: false });
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
const isFormUrlEncoded = Object.entries(this.def.headers || {}).some(
|
|
255
|
+
([k, v]) => k.toLowerCase() === "content-type" && v.includes("application/x-www-form-urlencoded")
|
|
256
|
+
);
|
|
257
|
+
let payloadPtr = 0, payloadLen = 0;
|
|
258
|
+
if (this.def.payload !== void 0 && this.def.payload !== null) {
|
|
259
|
+
const safePayload = this.def.serializer ? this.def.serializer(this.def.payload) : this.def.payload;
|
|
260
|
+
let payloadBytes;
|
|
261
|
+
if (isFormUrlEncoded && typeof safePayload === "object") {
|
|
262
|
+
const params = new URLSearchParams();
|
|
263
|
+
for (const [k, v] of Object.entries(safePayload))
|
|
264
|
+
params.append(k, String(v));
|
|
265
|
+
payloadBytes = new TextEncoder().encode(params.toString());
|
|
266
|
+
} else {
|
|
267
|
+
payloadBytes = new TextEncoder().encode(JSON.stringify(safePayload));
|
|
268
|
+
}
|
|
269
|
+
payloadPtr = (0, import_atmx_web.allocBytes)(payloadBytes);
|
|
270
|
+
payloadLen = payloadBytes.length;
|
|
271
|
+
}
|
|
272
|
+
const nsStr = (0, import_atmx_web.allocString)(this.def.namespace);
|
|
273
|
+
const mStr = (0, import_atmx_web.allocString)(this.def.method);
|
|
274
|
+
const pStr = (0, import_atmx_web.allocString)(path);
|
|
275
|
+
const tpStr = (0, import_atmx_web.allocString)("");
|
|
276
|
+
const hStr = (0, import_atmx_web.allocString)(
|
|
277
|
+
this.def.headers ? JSON.stringify(this.def.headers) : ""
|
|
278
|
+
);
|
|
279
|
+
import_atmx_web.wasmEngine.axiom_wasm_call(
|
|
280
|
+
reqId,
|
|
281
|
+
nsStr.ptr,
|
|
282
|
+
nsStr.len,
|
|
283
|
+
this.def.endpointId,
|
|
284
|
+
mStr.ptr,
|
|
285
|
+
mStr.len,
|
|
286
|
+
pStr.ptr,
|
|
287
|
+
pStr.len,
|
|
288
|
+
tpStr.ptr,
|
|
289
|
+
tpStr.len,
|
|
290
|
+
hStr.ptr,
|
|
291
|
+
hStr.len,
|
|
292
|
+
payloadPtr,
|
|
293
|
+
payloadLen
|
|
294
|
+
);
|
|
295
|
+
import_atmx_web.wasmEngine.axiom_free_memory(nsStr.ptr, nsStr.len);
|
|
296
|
+
import_atmx_web.wasmEngine.axiom_free_memory(mStr.ptr, mStr.len);
|
|
297
|
+
import_atmx_web.wasmEngine.axiom_free_memory(pStr.ptr, pStr.len);
|
|
298
|
+
import_atmx_web.wasmEngine.axiom_free_memory(tpStr.ptr, tpStr.len);
|
|
299
|
+
import_atmx_web.wasmEngine.axiom_free_memory(hStr.ptr, hStr.len);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// src/core/QueryManager.ts
|
|
304
|
+
var QueryManager = class {
|
|
305
|
+
constructor() {
|
|
306
|
+
__publicField(this, "queries", /* @__PURE__ */ new Map());
|
|
307
|
+
}
|
|
308
|
+
buildKey(namespace, endpointId, args) {
|
|
309
|
+
return `${namespace}:${endpointId}:${JSON.stringify(args)}`;
|
|
310
|
+
}
|
|
311
|
+
getQuery(def) {
|
|
312
|
+
const key = this.buildKey(def.namespace, def.endpointId, def.args);
|
|
313
|
+
if (this.queries.has(key)) {
|
|
314
|
+
return this.queries.get(key);
|
|
315
|
+
}
|
|
316
|
+
const newQuery = new ActiveQuery(key, def);
|
|
317
|
+
this.queries.set(key, newQuery);
|
|
318
|
+
return newQuery;
|
|
319
|
+
}
|
|
320
|
+
invalidate(namespace, endpointId, args) {
|
|
321
|
+
const key = this.buildKey(namespace, endpointId, args);
|
|
322
|
+
const query = this.queries.get(key);
|
|
323
|
+
if (query) query.fetch(true);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
var axiomQueryManager = new QueryManager();
|
|
327
|
+
|
|
328
|
+
// src/hooks/useAxiomQuery.ts
|
|
329
|
+
function useAxiomQuery(queryDef, options = {}) {
|
|
330
|
+
const { isReady, config } = useAxiom();
|
|
331
|
+
const { enabled = true } = options;
|
|
332
|
+
const activeQuery = axiomQueryManager.getQuery(queryDef);
|
|
333
|
+
const state = (0, import_react4.useSyncExternalStore)(
|
|
334
|
+
(0, import_react4.useCallback)(
|
|
335
|
+
(onStoreChange) => activeQuery.subscribe(onStoreChange),
|
|
336
|
+
[activeQuery]
|
|
337
|
+
),
|
|
338
|
+
() => activeQuery.getState(),
|
|
339
|
+
() => activeQuery.getState()
|
|
340
|
+
);
|
|
341
|
+
(0, import_react4.useEffect)(() => {
|
|
342
|
+
if (!isReady || !enabled) return;
|
|
343
|
+
if (state.status === "idle") {
|
|
344
|
+
activeQuery.fetch(false, config?.debug);
|
|
345
|
+
}
|
|
346
|
+
}, [isReady, enabled, activeQuery, state.status, config?.debug]);
|
|
347
|
+
return {
|
|
348
|
+
data: state.data,
|
|
349
|
+
isLoading: state.status === "loading",
|
|
350
|
+
isFetching: state.isFetching,
|
|
351
|
+
source: state.source,
|
|
352
|
+
error: state.error,
|
|
353
|
+
state,
|
|
354
|
+
// Export raw state for <AxWhen>
|
|
355
|
+
refetch: () => activeQuery.fetch(true, config?.debug)
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// src/components/AxQuery.tsx
|
|
360
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
361
|
+
function AxQuery({
|
|
362
|
+
call,
|
|
363
|
+
children,
|
|
364
|
+
enabled = true
|
|
365
|
+
}) {
|
|
366
|
+
const result = useAxiomQuery(call, { enabled });
|
|
367
|
+
const content = typeof children === "function" ? children({
|
|
368
|
+
data: result.data,
|
|
369
|
+
state: result.state,
|
|
370
|
+
refetch: result.refetch
|
|
371
|
+
}) : children;
|
|
372
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AxiomDataContext.Provider, { value: result.state, children: content });
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/components/AxWhen.tsx
|
|
376
|
+
var import_react5 = require("react");
|
|
377
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
378
|
+
function AxWhen({ value, is, children }) {
|
|
379
|
+
const context = (0, import_react5.useContext)(AxiomDataContext);
|
|
380
|
+
const stateObj = value || context;
|
|
381
|
+
if (!stateObj) return null;
|
|
382
|
+
const expectedStates = is.split(",").map((s) => s.trim().toLowerCase());
|
|
383
|
+
let currentState = "idle";
|
|
384
|
+
if (stateObj.isMutating) {
|
|
385
|
+
currentState = "mutating";
|
|
386
|
+
} else if (stateObj.status === "loading") {
|
|
387
|
+
currentState = "loading";
|
|
388
|
+
} else if (stateObj.status === "error") {
|
|
389
|
+
currentState = "error";
|
|
390
|
+
} else if (stateObj.status === "success" || stateObj.data) {
|
|
391
|
+
currentState = "data";
|
|
392
|
+
}
|
|
393
|
+
if (expectedStates.includes("success") && stateObj.status === "success" && !stateObj.isMutating) {
|
|
394
|
+
currentState = "success";
|
|
395
|
+
}
|
|
396
|
+
if (expectedStates.includes(currentState)) {
|
|
397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
|
|
398
|
+
}
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// src/components/AxTrigger.tsx
|
|
403
|
+
var import_react6 = require("react");
|
|
404
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
405
|
+
var AxTrigger = ({ onTrigger, once = true, children }) => {
|
|
406
|
+
const elementRef = (0, import_react6.useRef)(null);
|
|
407
|
+
const hasTriggered = (0, import_react6.useRef)(false);
|
|
408
|
+
(0, import_react6.useEffect)(() => {
|
|
409
|
+
const observer = new IntersectionObserver((entries) => {
|
|
410
|
+
entries.forEach((entry) => {
|
|
411
|
+
if (entry.isIntersecting) {
|
|
412
|
+
if (once && hasTriggered.current) return;
|
|
413
|
+
onTrigger();
|
|
414
|
+
hasTriggered.current = true;
|
|
415
|
+
if (once) observer.unobserve(entry.target);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}, { threshold: 0.1 });
|
|
419
|
+
if (elementRef.current) {
|
|
420
|
+
observer.observe(elementRef.current);
|
|
421
|
+
}
|
|
422
|
+
return () => observer.disconnect();
|
|
423
|
+
}, [onTrigger, once]);
|
|
424
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: elementRef, children });
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
// src/hooks/useAxiomMutation.ts
|
|
428
|
+
var import_react7 = require("react");
|
|
429
|
+
function extractFieldError(error, fieldName) {
|
|
430
|
+
if (error?.code !== "ValidationError" || !error?.details) return null;
|
|
431
|
+
const lines = error.details.split("\n");
|
|
432
|
+
for (const line of lines) {
|
|
433
|
+
if (line.startsWith(fieldName + ":"))
|
|
434
|
+
return line.substring(fieldName.length + 1).trim();
|
|
435
|
+
}
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
function useAxiomMutation(mutationFn) {
|
|
439
|
+
const { isReady, config } = useAxiom();
|
|
440
|
+
const [state, setState] = (0, import_react7.useState)({
|
|
441
|
+
status: "idle",
|
|
442
|
+
data: null,
|
|
443
|
+
error: null,
|
|
444
|
+
isFetching: false,
|
|
445
|
+
isMutating: false,
|
|
446
|
+
source: null
|
|
447
|
+
});
|
|
448
|
+
const isMounted = (0, import_react7.useRef)(true);
|
|
449
|
+
(0, import_react7.useEffect)(() => {
|
|
450
|
+
isMounted.current = true;
|
|
451
|
+
return () => {
|
|
452
|
+
isMounted.current = false;
|
|
453
|
+
};
|
|
454
|
+
}, []);
|
|
455
|
+
const execute = (0, import_react7.useCallback)(
|
|
456
|
+
async (args, options) => {
|
|
457
|
+
if (!isReady || !config) return;
|
|
458
|
+
const rawDef = mutationFn(args);
|
|
459
|
+
rawDef.headers = options?.headers;
|
|
460
|
+
const reqId = getNextReqId();
|
|
461
|
+
if (isMounted.current)
|
|
462
|
+
setState({
|
|
463
|
+
status: "loading",
|
|
464
|
+
data: null,
|
|
465
|
+
error: null,
|
|
466
|
+
isFetching: false,
|
|
467
|
+
isMutating: true,
|
|
468
|
+
source: null
|
|
469
|
+
});
|
|
470
|
+
const syntheticRoute = {
|
|
471
|
+
id: rawDef.endpointId,
|
|
472
|
+
namespace: rawDef.namespace,
|
|
473
|
+
name: rawDef.name || "unknown",
|
|
474
|
+
method: rawDef.method,
|
|
475
|
+
pathTemplate: rawDef.path,
|
|
476
|
+
isStream: !!rawDef.isStream
|
|
477
|
+
};
|
|
478
|
+
const { path } = (0, import_atmx_web2.buildRequestPath)(syntheticRoute, rawDef.args);
|
|
479
|
+
const isFormUrlEncoded = Object.entries(rawDef.headers || {}).some(
|
|
480
|
+
([k, v]) => k.toLowerCase() === "content-type" && v.includes("application/x-www-form-urlencoded")
|
|
481
|
+
);
|
|
482
|
+
let payloadPtr = 0, payloadLen = 0, payloadObj = null;
|
|
483
|
+
if (rawDef.payload !== void 0 && rawDef.payload !== null) {
|
|
484
|
+
payloadObj = rawDef.serializer ? rawDef.serializer(rawDef.payload) : rawDef.payload;
|
|
485
|
+
let payloadBytes;
|
|
486
|
+
if (isFormUrlEncoded && typeof payloadObj === "object") {
|
|
487
|
+
const params = new URLSearchParams();
|
|
488
|
+
for (const [k, v] of Object.entries(payloadObj))
|
|
489
|
+
params.append(k, String(v));
|
|
490
|
+
payloadBytes = new TextEncoder().encode(params.toString());
|
|
491
|
+
} else {
|
|
492
|
+
payloadBytes = new TextEncoder().encode(JSON.stringify(payloadObj));
|
|
493
|
+
}
|
|
494
|
+
payloadPtr = (0, import_atmx_web.allocBytes)(payloadBytes);
|
|
495
|
+
payloadLen = payloadBytes.length;
|
|
496
|
+
}
|
|
497
|
+
if (config.debug) {
|
|
498
|
+
console.groupCollapsed(
|
|
499
|
+
`%c\u2794 WASM MUTATE [#${reqId}]`,
|
|
500
|
+
`color: #7c3aed; font-weight: bold;`
|
|
501
|
+
);
|
|
502
|
+
console.log("Namespace:", rawDef.namespace);
|
|
503
|
+
console.log("Endpoint ID:", rawDef.endpointId);
|
|
504
|
+
console.log("Path:", path);
|
|
505
|
+
console.log("Payload:", payloadObj);
|
|
506
|
+
console.groupEnd();
|
|
507
|
+
}
|
|
508
|
+
import_atmx_web3.pendingRequests.set(reqId, {
|
|
509
|
+
isStream: !!rawDef.isStream,
|
|
510
|
+
onResponse: (response) => {
|
|
511
|
+
if (!isMounted.current) return;
|
|
512
|
+
if (config.debug) {
|
|
513
|
+
const evtName = response.eventType === 1 ? "NetworkSuccess" : response.eventType === 2 ? "CacheHit" : response.eventType === 3 ? "CacheHitAndFetching" : response.eventType === 4 ? "Error" : "Complete";
|
|
514
|
+
console.groupCollapsed(
|
|
515
|
+
`%c\u2190 WASM RESP [#${reqId}]`,
|
|
516
|
+
`color: #059669; font-weight: bold;`
|
|
517
|
+
);
|
|
518
|
+
console.log("Event Type:", evtName);
|
|
519
|
+
if (response.data) console.log("Data:", response.data);
|
|
520
|
+
if (response.error) console.log("Error:", response.error);
|
|
521
|
+
console.groupEnd();
|
|
522
|
+
}
|
|
523
|
+
if (response.eventType === 4) {
|
|
524
|
+
setState({
|
|
525
|
+
status: "error",
|
|
526
|
+
error: response.error || null,
|
|
527
|
+
isFetching: false,
|
|
528
|
+
isMutating: false,
|
|
529
|
+
data: null,
|
|
530
|
+
source: null
|
|
531
|
+
});
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
if (response.data) {
|
|
535
|
+
try {
|
|
536
|
+
let source = "network";
|
|
537
|
+
if (response.eventType === 2 || response.eventType === 3)
|
|
538
|
+
source = "cache";
|
|
539
|
+
setState({
|
|
540
|
+
status: "success",
|
|
541
|
+
data: rawDef.decoder(response.data),
|
|
542
|
+
error: null,
|
|
543
|
+
isFetching: false,
|
|
544
|
+
isMutating: false,
|
|
545
|
+
source
|
|
546
|
+
});
|
|
547
|
+
} catch (e) {
|
|
548
|
+
setState({
|
|
549
|
+
status: "error",
|
|
550
|
+
error: {
|
|
551
|
+
message: "Decoding failed",
|
|
552
|
+
details: String(e)
|
|
553
|
+
},
|
|
554
|
+
isFetching: false,
|
|
555
|
+
isMutating: false,
|
|
556
|
+
data: null,
|
|
557
|
+
source: null
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
},
|
|
562
|
+
onComplete: () => {
|
|
563
|
+
if (isMounted.current)
|
|
564
|
+
setState((prev) => ({
|
|
565
|
+
...prev,
|
|
566
|
+
isMutating: false,
|
|
567
|
+
isFetching: false
|
|
568
|
+
}));
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
const nsStr = (0, import_atmx_web.allocString)(rawDef.namespace);
|
|
572
|
+
const mStr = (0, import_atmx_web.allocString)(rawDef.method);
|
|
573
|
+
const pStr = (0, import_atmx_web.allocString)(path);
|
|
574
|
+
const tpStr = (0, import_atmx_web.allocString)("");
|
|
575
|
+
const hStr = (0, import_atmx_web.allocString)(
|
|
576
|
+
rawDef.headers ? JSON.stringify(rawDef.headers) : ""
|
|
577
|
+
);
|
|
578
|
+
import_atmx_web.wasmEngine.axiom_wasm_call(
|
|
579
|
+
reqId,
|
|
580
|
+
nsStr.ptr,
|
|
581
|
+
nsStr.len,
|
|
582
|
+
rawDef.endpointId,
|
|
583
|
+
mStr.ptr,
|
|
584
|
+
mStr.len,
|
|
585
|
+
pStr.ptr,
|
|
586
|
+
pStr.len,
|
|
587
|
+
tpStr.ptr,
|
|
588
|
+
tpStr.len,
|
|
589
|
+
hStr.ptr,
|
|
590
|
+
hStr.len,
|
|
591
|
+
payloadPtr,
|
|
592
|
+
payloadLen
|
|
593
|
+
);
|
|
594
|
+
import_atmx_web.wasmEngine.axiom_free_memory(nsStr.ptr, nsStr.len);
|
|
595
|
+
import_atmx_web.wasmEngine.axiom_free_memory(mStr.ptr, mStr.len);
|
|
596
|
+
import_atmx_web.wasmEngine.axiom_free_memory(pStr.ptr, pStr.len);
|
|
597
|
+
import_atmx_web.wasmEngine.axiom_free_memory(tpStr.ptr, tpStr.len);
|
|
598
|
+
import_atmx_web.wasmEngine.axiom_free_memory(hStr.ptr, hStr.len);
|
|
599
|
+
},
|
|
600
|
+
[isReady, config, mutationFn]
|
|
601
|
+
);
|
|
602
|
+
return {
|
|
603
|
+
execute,
|
|
604
|
+
state,
|
|
605
|
+
data: state.data,
|
|
606
|
+
isMutating: state.isMutating,
|
|
607
|
+
error: state.error,
|
|
608
|
+
getFieldError: (fieldName) => extractFieldError(state.error, fieldName)
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
612
|
+
0 && (module.exports = {
|
|
613
|
+
AxQuery,
|
|
614
|
+
AxTrigger,
|
|
615
|
+
AxWhen,
|
|
616
|
+
AxiomContext,
|
|
617
|
+
AxiomDataContext,
|
|
618
|
+
AxiomProvider,
|
|
619
|
+
axiomQueryManager,
|
|
620
|
+
clearAuthToken,
|
|
621
|
+
setAuthToken,
|
|
622
|
+
useAxiom,
|
|
623
|
+
useAxiomContext,
|
|
624
|
+
useAxiomData,
|
|
625
|
+
useAxiomMutation,
|
|
626
|
+
useAxiomQuery
|
|
627
|
+
});
|
|
628
|
+
//# sourceMappingURL=index.js.map
|