@fractalshq/sync 0.0.4 → 0.0.6

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.
@@ -0,0 +1,249 @@
1
+ import {
2
+ __objRest,
3
+ __spreadProps,
4
+ __spreadValues
5
+ } from "./chunk-FWCSY2DS.mjs";
6
+
7
+ // src/core/constants.ts
8
+ var MEMO_PROGRAM_ID = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
9
+ var XNET_2022_MINT = "xNETbUB7cRb3AAu2pNG2pUwQcJ2BHcktfvSB8x1Pq6L";
10
+ var DEFAULT_RPC_ENDPOINT = process.env.NEXT_PUBLIC_SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
11
+ var DISTRIBUTION_MEMO_PREFIX = "dist";
12
+
13
+ // src/core/helpers.ts
14
+ function buildDistributionMemoTag(distributionId, action = "claim") {
15
+ return `${DISTRIBUTION_MEMO_PREFIX}:${distributionId}:${action}`;
16
+ }
17
+ function assertTruthy(value, message) {
18
+ if (value === null || value === void 0) {
19
+ throw new Error(message);
20
+ }
21
+ return value;
22
+ }
23
+
24
+ // src/core/persistence.ts
25
+ var STORAGE_PREFIX = "distribution:persistence-warning:";
26
+ var PERSISTENCE_WARNING_EVENT = "distribution:persistence-warning";
27
+ function isBrowser() {
28
+ return typeof window !== "undefined" && typeof localStorage !== "undefined";
29
+ }
30
+ function persistToStorage(record) {
31
+ if (!isBrowser()) return;
32
+ try {
33
+ localStorage.setItem(`${STORAGE_PREFIX}${record.id}`, JSON.stringify(record));
34
+ } catch (error) {
35
+ console.error("[sync:persistence-warning] Failed to write to localStorage", error);
36
+ }
37
+ }
38
+ function emitWarning(record) {
39
+ if (!isBrowser()) return;
40
+ try {
41
+ window.dispatchEvent(new CustomEvent(PERSISTENCE_WARNING_EVENT, { detail: record }));
42
+ } catch (error) {
43
+ console.error("[sync:persistence-warning] Failed to emit warning event", error);
44
+ }
45
+ }
46
+ function recordPersistenceWarning(input) {
47
+ var _a2;
48
+ if (!isBrowser()) return void 0;
49
+ const record = __spreadProps(__spreadValues({}, input), {
50
+ createdAt: (_a2 = input.createdAt) != null ? _a2 : Date.now()
51
+ });
52
+ persistToStorage(record);
53
+ emitWarning(record);
54
+ return record;
55
+ }
56
+ function handlePersistenceWarningResponse(response) {
57
+ var _a2;
58
+ if (!isBrowser() || !response || typeof response !== "object") return;
59
+ const warning = response.persistenceWarning;
60
+ if (!warning) return;
61
+ const distributionId = warning.distributionId || response.distributionId || "unknown";
62
+ const exportJson = (_a2 = response.exportJson) != null ? _a2 : warning.exportJson;
63
+ const reason = warning.reason || "persist_distribution_failed";
64
+ const message = warning.message || "We were unable to save your distribution draft. Download the JSON to avoid data loss.";
65
+ const key = warning.id || `${distributionId}:${reason}:${Date.now()}`;
66
+ recordPersistenceWarning({
67
+ id: key,
68
+ distributionId,
69
+ reason,
70
+ message,
71
+ detail: warning.detail,
72
+ exportJson
73
+ });
74
+ }
75
+ function loadPersistenceWarnings() {
76
+ if (!isBrowser()) return [];
77
+ const records = [];
78
+ try {
79
+ for (let i = 0; i < localStorage.length; i++) {
80
+ const key = localStorage.key(i);
81
+ if (!key || !key.startsWith(STORAGE_PREFIX)) continue;
82
+ const raw = localStorage.getItem(key);
83
+ if (!raw) continue;
84
+ try {
85
+ const parsed = JSON.parse(raw);
86
+ if (parsed && typeof parsed === "object") {
87
+ records.push(parsed);
88
+ }
89
+ } catch (e) {
90
+ }
91
+ }
92
+ } catch (error) {
93
+ console.error("[sync:persistence-warning] Failed to load warnings", error);
94
+ }
95
+ return records.sort((a, b) => b.createdAt - a.createdAt);
96
+ }
97
+ function clearPersistenceWarning(id) {
98
+ if (!isBrowser()) return;
99
+ try {
100
+ localStorage.removeItem(`${STORAGE_PREFIX}${id}`);
101
+ } catch (e) {
102
+ }
103
+ }
104
+
105
+ // src/core/http.ts
106
+ var FALLBACK_BASE_PATH = "/api/v1/fractals-sync";
107
+ var _a, _b;
108
+ var ENV_BASE_PATH = typeof process !== "undefined" && (((_a = process.env) == null ? void 0 : _a.NEXT_PUBLIC_SYNC_PATH) || ((_b = process.env) == null ? void 0 : _b.NEXT_PUBLIC_FRACTALS_SYNC_PATH)) || void 0;
109
+ var DEFAULT_BASE_PATH = sanitizeBasePath(ENV_BASE_PATH || FALLBACK_BASE_PATH);
110
+ function resolveRequestConfig(options) {
111
+ return {
112
+ basePath: sanitizeBasePath((options == null ? void 0 : options.basePath) || DEFAULT_BASE_PATH),
113
+ fetcher: resolveFetcher(options == null ? void 0 : options.fetcher)
114
+ };
115
+ }
116
+ var SyncReactError = class extends Error {
117
+ constructor(status, code, details) {
118
+ super(code || `Sync request failed with status ${status}`);
119
+ this.status = status;
120
+ this.code = code;
121
+ this.details = details;
122
+ this.name = "SyncReactError";
123
+ }
124
+ };
125
+ async function requestJSON(config, path, init) {
126
+ var _a2;
127
+ const url = buildUrl(config.basePath, path);
128
+ const requestInit = prepareInit(init);
129
+ requestInit.credentials = (_a2 = requestInit.credentials) != null ? _a2 : isRelativeUrl(url) ? "include" : void 0;
130
+ const response = await config.fetcher(url, requestInit);
131
+ const payload = await parseResponseBody(response);
132
+ if (!response.ok) {
133
+ const errorCode = typeof payload === "object" && payload && "error" in payload ? String(payload.error) : void 0;
134
+ throw new SyncReactError(response.status, errorCode, payload);
135
+ }
136
+ return payload;
137
+ }
138
+ function resolveFetcher(custom) {
139
+ if (custom) return custom;
140
+ if (typeof fetch === "function") return fetch.bind(globalThis);
141
+ throw new Error("Global fetch is not available. Provide a fetcher via Sync configuration.");
142
+ }
143
+ function sanitizeBasePath(path) {
144
+ if (!path) return FALLBACK_BASE_PATH;
145
+ const trimmed = path.trim();
146
+ if (!trimmed || trimmed === "/") return "/";
147
+ return trimmed.replace(/\/+$/, "");
148
+ }
149
+ function buildUrl(basePath, path) {
150
+ if (path && isAbsoluteUrl(path)) return path;
151
+ const normalizedBase = sanitizeBasePath(basePath);
152
+ const suffix = path ? `/${path.replace(/^\/+/, "")}` : "";
153
+ if (!normalizedBase || normalizedBase === "/") {
154
+ return suffix ? suffix : normalizedBase;
155
+ }
156
+ return `${normalizedBase}${suffix}`;
157
+ }
158
+ function isAbsoluteUrl(path) {
159
+ return /^https?:\/\//i.test(path);
160
+ }
161
+ function isRelativeUrl(path) {
162
+ return !isAbsoluteUrl(path);
163
+ }
164
+ function prepareInit(init) {
165
+ const finalInit = __spreadValues({}, init);
166
+ if ((init == null ? void 0 : init.headers) instanceof Headers) {
167
+ const cloned = new Headers(init.headers);
168
+ if (!cloned.has("content-type")) cloned.set("content-type", "application/json");
169
+ finalInit.headers = cloned;
170
+ return finalInit;
171
+ }
172
+ const headers = new Headers(init == null ? void 0 : init.headers);
173
+ if (!headers.has("content-type")) {
174
+ headers.set("content-type", "application/json");
175
+ }
176
+ finalInit.headers = headers;
177
+ return finalInit;
178
+ }
179
+ async function parseResponseBody(response) {
180
+ if (response.status === 204) return void 0;
181
+ const text = await response.text();
182
+ if (!text) return void 0;
183
+ try {
184
+ return JSON.parse(text);
185
+ } catch (e) {
186
+ return text;
187
+ }
188
+ }
189
+
190
+ // src/core/api.ts
191
+ async function buildDistributionTransaction(input, options) {
192
+ const config = resolveRequestConfig(options);
193
+ const path = (input == null ? void 0 : input.distributionId) ? `/distributions/${encodeURIComponent(input.distributionId)}/create-transaction` : "/distributions/create-transaction";
194
+ const payload = await requestJSON(config, path, {
195
+ method: "POST",
196
+ body: JSON.stringify(input)
197
+ });
198
+ handlePersistenceWarningResponse(payload);
199
+ return payload;
200
+ }
201
+ async function commitDistributionSignature(input, options) {
202
+ const distributionId = input == null ? void 0 : input.distributionId;
203
+ if (!distributionId) {
204
+ throw new SyncReactError(400, "distribution_id_required");
205
+ }
206
+ const config = resolveRequestConfig(options);
207
+ const _a2 = input, { distributionId: _unused } = _a2, body = __objRest(_a2, ["distributionId"]);
208
+ return requestJSON(
209
+ config,
210
+ `/distributions/${encodeURIComponent(distributionId)}/commit`,
211
+ {
212
+ method: "POST",
213
+ body: JSON.stringify(body)
214
+ }
215
+ );
216
+ }
217
+ async function prepareDistributionDraft(input, options) {
218
+ const config = resolveRequestConfig(options);
219
+ return requestJSON(config, "/distributions/prepare", {
220
+ method: "POST",
221
+ body: JSON.stringify(input)
222
+ });
223
+ }
224
+
225
+ export {
226
+ MEMO_PROGRAM_ID,
227
+ XNET_2022_MINT,
228
+ DEFAULT_RPC_ENDPOINT,
229
+ DISTRIBUTION_MEMO_PREFIX,
230
+ buildDistributionMemoTag,
231
+ assertTruthy,
232
+ PERSISTENCE_WARNING_EVENT,
233
+ recordPersistenceWarning,
234
+ handlePersistenceWarningResponse,
235
+ loadPersistenceWarnings,
236
+ clearPersistenceWarning,
237
+ DEFAULT_BASE_PATH,
238
+ resolveRequestConfig,
239
+ SyncReactError,
240
+ requestJSON,
241
+ resolveFetcher,
242
+ sanitizeBasePath,
243
+ buildUrl,
244
+ isAbsoluteUrl,
245
+ isRelativeUrl,
246
+ buildDistributionTransaction,
247
+ commitDistributionSignature,
248
+ prepareDistributionDraft
249
+ };
@@ -1,4 +1,4 @@
1
- export { B as BuildClaimTransactionRequest, l as BuildClaimTransactionResponse, C as ClaimAllocation, e as ClaimCommitRequest, p as ClaimHistoryItem, q as ClaimHistoryResponse, b as ClaimTransactionInstruction, c as ClaimTransactionRequest, d as ClaimTransactionResponse, f as ClaimableDistribution, o as ClaimableResponse, m as CommitClaimRequest, n as CommitClaimResponse, j as CommitDistributionRequest, k as CommitDistributionResponse, h as CreateDistributionRequest, i as CreateDistributionResponse, a as Distribution, D as DistributionStatus, H as HealthResponse, L as ListDistributionsRequest, g as ListDistributionsResponse } from '../api-CQqyHbnT.mjs';
1
+ export { r as BuildClaimTransactionRequest, s as BuildClaimTransactionResponse, B as BuildDistributionTransactionRequest, m as BuildDistributionTransactionResponse, C as ClaimAllocation, e as ClaimCommitRequest, w as ClaimHistoryItem, x as ClaimHistoryResponse, b as ClaimTransactionInstruction, c as ClaimTransactionRequest, d as ClaimTransactionResponse, f as ClaimableDistribution, v as ClaimableResponse, t as CommitClaimRequest, u as CommitClaimResponse, o as CommitDistributionRequest, p as CommitDistributionResponse, q as CommitDistributionSignatureInput, l as CreateDistributionRequest, n as CreateDistributionResponse, G as DEFAULT_BASE_PATH, a as Distribution, i as DistributionInstruction, j as DistributionPersistenceWarning, h as DistributionRecipientInput, D as DistributionStatus, k as DistributionTransactionPayload, F as Fetcher, H as HealthResponse, L as ListDistributionsRequest, g as ListDistributionsResponse, P as PrepareDistributionDraftRequest, y as PrepareDistributionDraftResponse, K as SyncReactError, I as SyncRequestConfig, S as SyncRequestOptions, z as buildDistributionTransaction, Q as buildUrl, A as commitDistributionSignature, R as isAbsoluteUrl, T as isRelativeUrl, E as prepareDistributionDraft, M as requestJSON, N as resolveFetcher, J as resolveRequestConfig, O as sanitizeBasePath } from '../api-C0dGK-PK.mjs';
2
2
 
3
3
  declare const MEMO_PROGRAM_ID = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
4
4
  declare const XNET_2022_MINT = "xNETbUB7cRb3AAu2pNG2pUwQcJ2BHcktfvSB8x1Pq6L";
@@ -8,4 +8,21 @@ declare const DISTRIBUTION_MEMO_PREFIX = "dist";
8
8
  declare function buildDistributionMemoTag(distributionId: string, action?: "claim" | "commit"): string;
9
9
  declare function assertTruthy<T>(value: T | null | undefined, message: string): T;
10
10
 
11
- export { DEFAULT_RPC_ENDPOINT, DISTRIBUTION_MEMO_PREFIX, MEMO_PROGRAM_ID, XNET_2022_MINT, assertTruthy, buildDistributionMemoTag };
11
+ declare const PERSISTENCE_WARNING_EVENT = "distribution:persistence-warning";
12
+ interface PersistenceWarningRecord {
13
+ id: string;
14
+ distributionId: string;
15
+ reason: string;
16
+ message: string;
17
+ detail?: unknown;
18
+ exportJson?: any;
19
+ createdAt: number;
20
+ }
21
+ declare function recordPersistenceWarning(input: Omit<PersistenceWarningRecord, "createdAt"> & {
22
+ createdAt?: number;
23
+ }): PersistenceWarningRecord | undefined;
24
+ declare function handlePersistenceWarningResponse(response: any): void;
25
+ declare function loadPersistenceWarnings(): PersistenceWarningRecord[];
26
+ declare function clearPersistenceWarning(id: string): void;
27
+
28
+ export { DEFAULT_RPC_ENDPOINT, DISTRIBUTION_MEMO_PREFIX, MEMO_PROGRAM_ID, PERSISTENCE_WARNING_EVENT, type PersistenceWarningRecord, XNET_2022_MINT, assertTruthy, buildDistributionMemoTag, clearPersistenceWarning, handlePersistenceWarningResponse, loadPersistenceWarnings, recordPersistenceWarning };
@@ -1,4 +1,4 @@
1
- export { B as BuildClaimTransactionRequest, l as BuildClaimTransactionResponse, C as ClaimAllocation, e as ClaimCommitRequest, p as ClaimHistoryItem, q as ClaimHistoryResponse, b as ClaimTransactionInstruction, c as ClaimTransactionRequest, d as ClaimTransactionResponse, f as ClaimableDistribution, o as ClaimableResponse, m as CommitClaimRequest, n as CommitClaimResponse, j as CommitDistributionRequest, k as CommitDistributionResponse, h as CreateDistributionRequest, i as CreateDistributionResponse, a as Distribution, D as DistributionStatus, H as HealthResponse, L as ListDistributionsRequest, g as ListDistributionsResponse } from '../api-CQqyHbnT.js';
1
+ export { r as BuildClaimTransactionRequest, s as BuildClaimTransactionResponse, B as BuildDistributionTransactionRequest, m as BuildDistributionTransactionResponse, C as ClaimAllocation, e as ClaimCommitRequest, w as ClaimHistoryItem, x as ClaimHistoryResponse, b as ClaimTransactionInstruction, c as ClaimTransactionRequest, d as ClaimTransactionResponse, f as ClaimableDistribution, v as ClaimableResponse, t as CommitClaimRequest, u as CommitClaimResponse, o as CommitDistributionRequest, p as CommitDistributionResponse, q as CommitDistributionSignatureInput, l as CreateDistributionRequest, n as CreateDistributionResponse, G as DEFAULT_BASE_PATH, a as Distribution, i as DistributionInstruction, j as DistributionPersistenceWarning, h as DistributionRecipientInput, D as DistributionStatus, k as DistributionTransactionPayload, F as Fetcher, H as HealthResponse, L as ListDistributionsRequest, g as ListDistributionsResponse, P as PrepareDistributionDraftRequest, y as PrepareDistributionDraftResponse, K as SyncReactError, I as SyncRequestConfig, S as SyncRequestOptions, z as buildDistributionTransaction, Q as buildUrl, A as commitDistributionSignature, R as isAbsoluteUrl, T as isRelativeUrl, E as prepareDistributionDraft, M as requestJSON, N as resolveFetcher, J as resolveRequestConfig, O as sanitizeBasePath } from '../api-C0dGK-PK.js';
2
2
 
3
3
  declare const MEMO_PROGRAM_ID = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
4
4
  declare const XNET_2022_MINT = "xNETbUB7cRb3AAu2pNG2pUwQcJ2BHcktfvSB8x1Pq6L";
@@ -8,4 +8,21 @@ declare const DISTRIBUTION_MEMO_PREFIX = "dist";
8
8
  declare function buildDistributionMemoTag(distributionId: string, action?: "claim" | "commit"): string;
9
9
  declare function assertTruthy<T>(value: T | null | undefined, message: string): T;
10
10
 
11
- export { DEFAULT_RPC_ENDPOINT, DISTRIBUTION_MEMO_PREFIX, MEMO_PROGRAM_ID, XNET_2022_MINT, assertTruthy, buildDistributionMemoTag };
11
+ declare const PERSISTENCE_WARNING_EVENT = "distribution:persistence-warning";
12
+ interface PersistenceWarningRecord {
13
+ id: string;
14
+ distributionId: string;
15
+ reason: string;
16
+ message: string;
17
+ detail?: unknown;
18
+ exportJson?: any;
19
+ createdAt: number;
20
+ }
21
+ declare function recordPersistenceWarning(input: Omit<PersistenceWarningRecord, "createdAt"> & {
22
+ createdAt?: number;
23
+ }): PersistenceWarningRecord | undefined;
24
+ declare function handlePersistenceWarningResponse(response: any): void;
25
+ declare function loadPersistenceWarnings(): PersistenceWarningRecord[];
26
+ declare function clearPersistenceWarning(id: string): void;
27
+
28
+ export { DEFAULT_RPC_ENDPOINT, DISTRIBUTION_MEMO_PREFIX, MEMO_PROGRAM_ID, PERSISTENCE_WARNING_EVENT, type PersistenceWarningRecord, XNET_2022_MINT, assertTruthy, buildDistributionMemoTag, clearPersistenceWarning, handlePersistenceWarningResponse, loadPersistenceWarnings, recordPersistenceWarning };
@@ -1,8 +1,37 @@
1
1
  "use strict";
2
2
  var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __spreadValues = (a, b) => {
12
+ for (var prop in b || (b = {}))
13
+ if (__hasOwnProp.call(b, prop))
14
+ __defNormalProp(a, prop, b[prop]);
15
+ if (__getOwnPropSymbols)
16
+ for (var prop of __getOwnPropSymbols(b)) {
17
+ if (__propIsEnum.call(b, prop))
18
+ __defNormalProp(a, prop, b[prop]);
19
+ }
20
+ return a;
21
+ };
22
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
+ var __objRest = (source, exclude) => {
24
+ var target = {};
25
+ for (var prop in source)
26
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
27
+ target[prop] = source[prop];
28
+ if (source != null && __getOwnPropSymbols)
29
+ for (var prop of __getOwnPropSymbols(source)) {
30
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
31
+ target[prop] = source[prop];
32
+ }
33
+ return target;
34
+ };
6
35
  var __export = (target, all) => {
7
36
  for (var name in all)
8
37
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -20,12 +49,29 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
49
  // src/core/index.ts
21
50
  var core_exports = {};
22
51
  __export(core_exports, {
52
+ DEFAULT_BASE_PATH: () => DEFAULT_BASE_PATH,
23
53
  DEFAULT_RPC_ENDPOINT: () => DEFAULT_RPC_ENDPOINT,
24
54
  DISTRIBUTION_MEMO_PREFIX: () => DISTRIBUTION_MEMO_PREFIX,
25
55
  MEMO_PROGRAM_ID: () => MEMO_PROGRAM_ID,
56
+ PERSISTENCE_WARNING_EVENT: () => PERSISTENCE_WARNING_EVENT,
57
+ SyncReactError: () => SyncReactError,
26
58
  XNET_2022_MINT: () => XNET_2022_MINT,
27
59
  assertTruthy: () => assertTruthy,
28
- buildDistributionMemoTag: () => buildDistributionMemoTag
60
+ buildDistributionMemoTag: () => buildDistributionMemoTag,
61
+ buildDistributionTransaction: () => buildDistributionTransaction,
62
+ buildUrl: () => buildUrl,
63
+ clearPersistenceWarning: () => clearPersistenceWarning,
64
+ commitDistributionSignature: () => commitDistributionSignature,
65
+ handlePersistenceWarningResponse: () => handlePersistenceWarningResponse,
66
+ isAbsoluteUrl: () => isAbsoluteUrl,
67
+ isRelativeUrl: () => isRelativeUrl,
68
+ loadPersistenceWarnings: () => loadPersistenceWarnings,
69
+ prepareDistributionDraft: () => prepareDistributionDraft,
70
+ recordPersistenceWarning: () => recordPersistenceWarning,
71
+ requestJSON: () => requestJSON,
72
+ resolveFetcher: () => resolveFetcher,
73
+ resolveRequestConfig: () => resolveRequestConfig,
74
+ sanitizeBasePath: () => sanitizeBasePath
29
75
  });
30
76
  module.exports = __toCommonJS(core_exports);
31
77
 
@@ -45,12 +91,230 @@ function assertTruthy(value, message) {
45
91
  }
46
92
  return value;
47
93
  }
94
+
95
+ // src/core/persistence.ts
96
+ var STORAGE_PREFIX = "distribution:persistence-warning:";
97
+ var PERSISTENCE_WARNING_EVENT = "distribution:persistence-warning";
98
+ function isBrowser() {
99
+ return typeof window !== "undefined" && typeof localStorage !== "undefined";
100
+ }
101
+ function persistToStorage(record) {
102
+ if (!isBrowser()) return;
103
+ try {
104
+ localStorage.setItem(`${STORAGE_PREFIX}${record.id}`, JSON.stringify(record));
105
+ } catch (error) {
106
+ console.error("[sync:persistence-warning] Failed to write to localStorage", error);
107
+ }
108
+ }
109
+ function emitWarning(record) {
110
+ if (!isBrowser()) return;
111
+ try {
112
+ window.dispatchEvent(new CustomEvent(PERSISTENCE_WARNING_EVENT, { detail: record }));
113
+ } catch (error) {
114
+ console.error("[sync:persistence-warning] Failed to emit warning event", error);
115
+ }
116
+ }
117
+ function recordPersistenceWarning(input) {
118
+ var _a2;
119
+ if (!isBrowser()) return void 0;
120
+ const record = __spreadProps(__spreadValues({}, input), {
121
+ createdAt: (_a2 = input.createdAt) != null ? _a2 : Date.now()
122
+ });
123
+ persistToStorage(record);
124
+ emitWarning(record);
125
+ return record;
126
+ }
127
+ function handlePersistenceWarningResponse(response) {
128
+ var _a2;
129
+ if (!isBrowser() || !response || typeof response !== "object") return;
130
+ const warning = response.persistenceWarning;
131
+ if (!warning) return;
132
+ const distributionId = warning.distributionId || response.distributionId || "unknown";
133
+ const exportJson = (_a2 = response.exportJson) != null ? _a2 : warning.exportJson;
134
+ const reason = warning.reason || "persist_distribution_failed";
135
+ const message = warning.message || "We were unable to save your distribution draft. Download the JSON to avoid data loss.";
136
+ const key = warning.id || `${distributionId}:${reason}:${Date.now()}`;
137
+ recordPersistenceWarning({
138
+ id: key,
139
+ distributionId,
140
+ reason,
141
+ message,
142
+ detail: warning.detail,
143
+ exportJson
144
+ });
145
+ }
146
+ function loadPersistenceWarnings() {
147
+ if (!isBrowser()) return [];
148
+ const records = [];
149
+ try {
150
+ for (let i = 0; i < localStorage.length; i++) {
151
+ const key = localStorage.key(i);
152
+ if (!key || !key.startsWith(STORAGE_PREFIX)) continue;
153
+ const raw = localStorage.getItem(key);
154
+ if (!raw) continue;
155
+ try {
156
+ const parsed = JSON.parse(raw);
157
+ if (parsed && typeof parsed === "object") {
158
+ records.push(parsed);
159
+ }
160
+ } catch (e) {
161
+ }
162
+ }
163
+ } catch (error) {
164
+ console.error("[sync:persistence-warning] Failed to load warnings", error);
165
+ }
166
+ return records.sort((a, b) => b.createdAt - a.createdAt);
167
+ }
168
+ function clearPersistenceWarning(id) {
169
+ if (!isBrowser()) return;
170
+ try {
171
+ localStorage.removeItem(`${STORAGE_PREFIX}${id}`);
172
+ } catch (e) {
173
+ }
174
+ }
175
+
176
+ // src/core/http.ts
177
+ var FALLBACK_BASE_PATH = "/api/v1/fractals-sync";
178
+ var _a, _b;
179
+ var ENV_BASE_PATH = typeof process !== "undefined" && (((_a = process.env) == null ? void 0 : _a.NEXT_PUBLIC_SYNC_PATH) || ((_b = process.env) == null ? void 0 : _b.NEXT_PUBLIC_FRACTALS_SYNC_PATH)) || void 0;
180
+ var DEFAULT_BASE_PATH = sanitizeBasePath(ENV_BASE_PATH || FALLBACK_BASE_PATH);
181
+ function resolveRequestConfig(options) {
182
+ return {
183
+ basePath: sanitizeBasePath((options == null ? void 0 : options.basePath) || DEFAULT_BASE_PATH),
184
+ fetcher: resolveFetcher(options == null ? void 0 : options.fetcher)
185
+ };
186
+ }
187
+ var SyncReactError = class extends Error {
188
+ constructor(status, code, details) {
189
+ super(code || `Sync request failed with status ${status}`);
190
+ this.status = status;
191
+ this.code = code;
192
+ this.details = details;
193
+ this.name = "SyncReactError";
194
+ }
195
+ };
196
+ async function requestJSON(config, path, init) {
197
+ var _a2;
198
+ const url = buildUrl(config.basePath, path);
199
+ const requestInit = prepareInit(init);
200
+ requestInit.credentials = (_a2 = requestInit.credentials) != null ? _a2 : isRelativeUrl(url) ? "include" : void 0;
201
+ const response = await config.fetcher(url, requestInit);
202
+ const payload = await parseResponseBody(response);
203
+ if (!response.ok) {
204
+ const errorCode = typeof payload === "object" && payload && "error" in payload ? String(payload.error) : void 0;
205
+ throw new SyncReactError(response.status, errorCode, payload);
206
+ }
207
+ return payload;
208
+ }
209
+ function resolveFetcher(custom) {
210
+ if (custom) return custom;
211
+ if (typeof fetch === "function") return fetch.bind(globalThis);
212
+ throw new Error("Global fetch is not available. Provide a fetcher via Sync configuration.");
213
+ }
214
+ function sanitizeBasePath(path) {
215
+ if (!path) return FALLBACK_BASE_PATH;
216
+ const trimmed = path.trim();
217
+ if (!trimmed || trimmed === "/") return "/";
218
+ return trimmed.replace(/\/+$/, "");
219
+ }
220
+ function buildUrl(basePath, path) {
221
+ if (path && isAbsoluteUrl(path)) return path;
222
+ const normalizedBase = sanitizeBasePath(basePath);
223
+ const suffix = path ? `/${path.replace(/^\/+/, "")}` : "";
224
+ if (!normalizedBase || normalizedBase === "/") {
225
+ return suffix ? suffix : normalizedBase;
226
+ }
227
+ return `${normalizedBase}${suffix}`;
228
+ }
229
+ function isAbsoluteUrl(path) {
230
+ return /^https?:\/\//i.test(path);
231
+ }
232
+ function isRelativeUrl(path) {
233
+ return !isAbsoluteUrl(path);
234
+ }
235
+ function prepareInit(init) {
236
+ const finalInit = __spreadValues({}, init);
237
+ if ((init == null ? void 0 : init.headers) instanceof Headers) {
238
+ const cloned = new Headers(init.headers);
239
+ if (!cloned.has("content-type")) cloned.set("content-type", "application/json");
240
+ finalInit.headers = cloned;
241
+ return finalInit;
242
+ }
243
+ const headers = new Headers(init == null ? void 0 : init.headers);
244
+ if (!headers.has("content-type")) {
245
+ headers.set("content-type", "application/json");
246
+ }
247
+ finalInit.headers = headers;
248
+ return finalInit;
249
+ }
250
+ async function parseResponseBody(response) {
251
+ if (response.status === 204) return void 0;
252
+ const text = await response.text();
253
+ if (!text) return void 0;
254
+ try {
255
+ return JSON.parse(text);
256
+ } catch (e) {
257
+ return text;
258
+ }
259
+ }
260
+
261
+ // src/core/api.ts
262
+ async function buildDistributionTransaction(input, options) {
263
+ const config = resolveRequestConfig(options);
264
+ const path = (input == null ? void 0 : input.distributionId) ? `/distributions/${encodeURIComponent(input.distributionId)}/create-transaction` : "/distributions/create-transaction";
265
+ const payload = await requestJSON(config, path, {
266
+ method: "POST",
267
+ body: JSON.stringify(input)
268
+ });
269
+ handlePersistenceWarningResponse(payload);
270
+ return payload;
271
+ }
272
+ async function commitDistributionSignature(input, options) {
273
+ const distributionId = input == null ? void 0 : input.distributionId;
274
+ if (!distributionId) {
275
+ throw new SyncReactError(400, "distribution_id_required");
276
+ }
277
+ const config = resolveRequestConfig(options);
278
+ const _a2 = input, { distributionId: _unused } = _a2, body = __objRest(_a2, ["distributionId"]);
279
+ return requestJSON(
280
+ config,
281
+ `/distributions/${encodeURIComponent(distributionId)}/commit`,
282
+ {
283
+ method: "POST",
284
+ body: JSON.stringify(body)
285
+ }
286
+ );
287
+ }
288
+ async function prepareDistributionDraft(input, options) {
289
+ const config = resolveRequestConfig(options);
290
+ return requestJSON(config, "/distributions/prepare", {
291
+ method: "POST",
292
+ body: JSON.stringify(input)
293
+ });
294
+ }
48
295
  // Annotate the CommonJS export names for ESM import in node:
49
296
  0 && (module.exports = {
297
+ DEFAULT_BASE_PATH,
50
298
  DEFAULT_RPC_ENDPOINT,
51
299
  DISTRIBUTION_MEMO_PREFIX,
52
300
  MEMO_PROGRAM_ID,
301
+ PERSISTENCE_WARNING_EVENT,
302
+ SyncReactError,
53
303
  XNET_2022_MINT,
54
304
  assertTruthy,
55
- buildDistributionMemoTag
305
+ buildDistributionMemoTag,
306
+ buildDistributionTransaction,
307
+ buildUrl,
308
+ clearPersistenceWarning,
309
+ commitDistributionSignature,
310
+ handlePersistenceWarningResponse,
311
+ isAbsoluteUrl,
312
+ isRelativeUrl,
313
+ loadPersistenceWarnings,
314
+ prepareDistributionDraft,
315
+ recordPersistenceWarning,
316
+ requestJSON,
317
+ resolveFetcher,
318
+ resolveRequestConfig,
319
+ sanitizeBasePath
56
320
  });
@@ -1,17 +1,51 @@
1
1
  import {
2
+ DEFAULT_BASE_PATH,
2
3
  DEFAULT_RPC_ENDPOINT,
3
4
  DISTRIBUTION_MEMO_PREFIX,
4
5
  MEMO_PROGRAM_ID,
6
+ PERSISTENCE_WARNING_EVENT,
7
+ SyncReactError,
5
8
  XNET_2022_MINT,
6
9
  assertTruthy,
7
- buildDistributionMemoTag
8
- } from "../chunk-TCJM2GIK.mjs";
9
- import "../chunk-I4E63NIC.mjs";
10
+ buildDistributionMemoTag,
11
+ buildDistributionTransaction,
12
+ buildUrl,
13
+ clearPersistenceWarning,
14
+ commitDistributionSignature,
15
+ handlePersistenceWarningResponse,
16
+ isAbsoluteUrl,
17
+ isRelativeUrl,
18
+ loadPersistenceWarnings,
19
+ prepareDistributionDraft,
20
+ recordPersistenceWarning,
21
+ requestJSON,
22
+ resolveFetcher,
23
+ resolveRequestConfig,
24
+ sanitizeBasePath
25
+ } from "../chunk-VXNOPXKB.mjs";
26
+ import "../chunk-FWCSY2DS.mjs";
10
27
  export {
28
+ DEFAULT_BASE_PATH,
11
29
  DEFAULT_RPC_ENDPOINT,
12
30
  DISTRIBUTION_MEMO_PREFIX,
13
31
  MEMO_PROGRAM_ID,
32
+ PERSISTENCE_WARNING_EVENT,
33
+ SyncReactError,
14
34
  XNET_2022_MINT,
15
35
  assertTruthy,
16
- buildDistributionMemoTag
36
+ buildDistributionMemoTag,
37
+ buildDistributionTransaction,
38
+ buildUrl,
39
+ clearPersistenceWarning,
40
+ commitDistributionSignature,
41
+ handlePersistenceWarningResponse,
42
+ isAbsoluteUrl,
43
+ isRelativeUrl,
44
+ loadPersistenceWarnings,
45
+ prepareDistributionDraft,
46
+ recordPersistenceWarning,
47
+ requestJSON,
48
+ resolveFetcher,
49
+ resolveRequestConfig,
50
+ sanitizeBasePath
17
51
  };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { ApiAuthRequest, GET, POST, SyncHandlerOptions, SyncServerClient, SyncServerOptions, createMethodHandler, syncRouteHandler } from './server/index.mjs';
2
- export { DEFAULT_RPC_ENDPOINT, DISTRIBUTION_MEMO_PREFIX, MEMO_PROGRAM_ID, XNET_2022_MINT, assertTruthy, buildDistributionMemoTag } from './core/index.mjs';
3
- export { B as BuildClaimTransactionRequest, l as BuildClaimTransactionResponse, C as ClaimAllocation, e as ClaimCommitRequest, p as ClaimHistoryItem, q as ClaimHistoryResponse, b as ClaimTransactionInstruction, c as ClaimTransactionRequest, d as ClaimTransactionResponse, f as ClaimableDistribution, o as ClaimableResponse, m as CommitClaimRequest, n as CommitClaimResponse, j as CommitDistributionRequest, k as CommitDistributionResponse, h as CreateDistributionRequest, i as CreateDistributionResponse, a as Distribution, D as DistributionStatus, H as HealthResponse, L as ListDistributionsRequest, g as ListDistributionsResponse } from './api-CQqyHbnT.mjs';
2
+ export { DEFAULT_RPC_ENDPOINT, DISTRIBUTION_MEMO_PREFIX, MEMO_PROGRAM_ID, PERSISTENCE_WARNING_EVENT, PersistenceWarningRecord, XNET_2022_MINT, assertTruthy, buildDistributionMemoTag, clearPersistenceWarning, handlePersistenceWarningResponse, loadPersistenceWarnings, recordPersistenceWarning } from './core/index.mjs';
3
+ export { r as BuildClaimTransactionRequest, s as BuildClaimTransactionResponse, B as BuildDistributionTransactionRequest, m as BuildDistributionTransactionResponse, C as ClaimAllocation, e as ClaimCommitRequest, w as ClaimHistoryItem, x as ClaimHistoryResponse, b as ClaimTransactionInstruction, c as ClaimTransactionRequest, d as ClaimTransactionResponse, f as ClaimableDistribution, v as ClaimableResponse, t as CommitClaimRequest, u as CommitClaimResponse, o as CommitDistributionRequest, p as CommitDistributionResponse, q as CommitDistributionSignatureInput, l as CreateDistributionRequest, n as CreateDistributionResponse, G as DEFAULT_BASE_PATH, a as Distribution, i as DistributionInstruction, j as DistributionPersistenceWarning, h as DistributionRecipientInput, D as DistributionStatus, k as DistributionTransactionPayload, F as Fetcher, H as HealthResponse, L as ListDistributionsRequest, g as ListDistributionsResponse, P as PrepareDistributionDraftRequest, y as PrepareDistributionDraftResponse, K as SyncReactError, I as SyncRequestConfig, S as SyncRequestOptions, z as buildDistributionTransaction, Q as buildUrl, A as commitDistributionSignature, R as isAbsoluteUrl, T as isRelativeUrl, E as prepareDistributionDraft, M as requestJSON, N as resolveFetcher, J as resolveRequestConfig, O as sanitizeBasePath } from './api-C0dGK-PK.mjs';