@le-space/browser 0.1.27 → 0.1.29

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/README.md CHANGED
@@ -25,6 +25,8 @@ That client should remain small and stable. It currently owns:
25
25
  - CRN listing
26
26
  - instance listing
27
27
  - message envelope lookup
28
+ - scheduler allocation lookup
29
+ - CRN allocation notify
28
30
  - deployment result inspection and polling
29
31
  - Aleph message broadcast helpers
30
32
 
package/index.d.ts CHANGED
@@ -143,6 +143,27 @@ interface DeploymentInspectionResult {
143
143
  rejectionReason: string | null;
144
144
  references: MessageReference[];
145
145
  }
146
+ interface InstanceAllocationNode {
147
+ node_id?: string;
148
+ url?: string;
149
+ ipv6?: string | null;
150
+ supports_ipv6?: boolean;
151
+ }
152
+ interface InstanceAllocationPeriod {
153
+ start_timestamp?: string;
154
+ duration_seconds?: number;
155
+ }
156
+ interface InstanceAllocation {
157
+ source: 'scheduler' | 'manual';
158
+ crnHash?: string | null;
159
+ crnUrl?: string | null;
160
+ node?: InstanceAllocationNode | null;
161
+ vmIpv6?: string | null;
162
+ period?: InstanceAllocationPeriod | null;
163
+ }
164
+ interface AllocationNotifyResult {
165
+ status: 'confirmed' | 'unconfirmed';
166
+ }
146
167
  interface AlephBroadcastMessage {
147
168
  sender: string;
148
169
  chain: AlephSenderChain;
@@ -169,10 +190,13 @@ interface BroadcastResult {
169
190
  interface AlephBrowserClient {
170
191
  apiHost: string;
171
192
  crnListUrl: string;
193
+ schedulerApiHost: string;
172
194
  fetchBalance(address: string): Promise<BalanceResponse>;
173
195
  fetchCrns(): Promise<Crn[]>;
174
196
  fetchInstances(address: string): Promise<InstanceMessage[]>;
175
197
  fetchMessageEnvelope(itemHash: string): Promise<AlephMessageEnvelope | null>;
198
+ fetchSchedulerAllocation(itemHash: string): Promise<InstanceAllocation | null>;
199
+ notifyCrnAllocation(crnUrl: string, itemHash: string): Promise<AllocationNotifyResult>;
176
200
  inspectDeploymentResult(itemHash: string, rootfsRef?: string): Promise<DeploymentInspectionResult>;
177
201
  waitForDeploymentResult(itemHash: string, rootfsRef?: string, attempts?: number, delayMs?: number): Promise<DeploymentInspectionResult>;
178
202
  broadcastInstanceMessage(message: AlephBroadcastMessage, sync?: boolean): Promise<BroadcastResult>;
@@ -220,10 +244,13 @@ declare function fetchWithTimeout(input: RequestInfo | URL, init?: RequestInit,
220
244
 
221
245
  declare const DEFAULT_ALEPH_API_HOST = "https://api2.aleph.im";
222
246
  declare const DEFAULT_CRN_LIST_URL = "https://crns-list.aleph.sh/crns.json";
247
+ declare const DEFAULT_ALEPH_SCHEDULER_API_HOST = "https://scheduler.api.aleph.cloud";
223
248
  declare function normalizeMessageStatus(status: unknown): MessageStatus;
224
249
  declare function fetchBalance(address: string, apiHost?: string): Promise<BalanceResponse>;
225
250
  declare function fetchCrns(url?: string): Promise<Crn[]>;
226
251
  declare function fetchInstances(address: string, apiHost?: string): Promise<InstanceMessage[]>;
252
+ declare function fetchSchedulerAllocation(itemHash: string, schedulerApiHost?: string): Promise<InstanceAllocation | null>;
253
+ declare function notifyCrnAllocation(crnUrl: string, itemHash: string): Promise<AllocationNotifyResult>;
227
254
  declare function fetchMessageEnvelope(itemHash: string, apiHost?: string): Promise<AlephMessageEnvelope | null>;
228
255
  declare function inspectDeploymentResult(itemHash: string, rootfsRef?: string, apiHost?: string): Promise<DeploymentInspectionResult>;
229
256
  declare function waitForDeploymentResult(itemHash: string, rootfsRef?: string, apiHost?: string, attempts?: number, delayMs?: number): Promise<DeploymentInspectionResult>;
@@ -233,6 +260,7 @@ declare function broadcastAlephMessage(message: AlephBroadcastMessage, apiHost?:
233
260
  interface CreateAlephBrowserClientOptions {
234
261
  apiHost?: string;
235
262
  crnListUrl?: string;
263
+ schedulerApiHost?: string;
236
264
  }
237
265
  declare function createAlephBrowserClient(options?: CreateAlephBrowserClientOptions): AlephBrowserClient;
238
266
 
@@ -251,4 +279,4 @@ declare const DEFAULT_ALEPH_AGGREGATE_ADDRESS = "0xFba561a84A537fCaa567bb7A2257e
251
279
  declare function parseInstancePricing(payload: unknown): InstancePricing;
252
280
  declare function fetchInstancePricing(apiHost?: string, aggregateAddress?: string): Promise<PricingState>;
253
281
 
254
- export { type AlephBroadcastMessage, type AlephBroadcastResponse, type AlephBrowserClient, type AlephMessageEnvelope, type AlephMessageType, type AlephSenderChain, BROWSER_PACKAGE_PLAN, type BalanceResponse, type BroadcastResult, type BrowserExtractionPhase, type BrowserPackagePlan, type ComputeUnit, type CreateAlephBrowserClientOptions, type Crn, type CrnListResponse, type CrnLocation, type CrnUsage, DEFAULT_ALEPH_AGGREGATE_ADDRESS, DEFAULT_ALEPH_API_HOST, DEFAULT_CRN_LIST_URL, DEFAULT_IPFS_GATEWAY_BASE_URL, DEFAULT_ROOTFS_MANIFEST_URL, type DeploymentInspectionResult, type GatewayProbeStatus, ITEM_HASH_RE, type InstanceMessage, type InstancePricing, type LoadRootfsManifestOptions, type MessageReference, type MessageStatus, type PaymentMode, type Price, type PricingState, type ReferenceStatus, type RootfsManifest, type RootfsManifestState, type RootfsRequiredPortForward, type RootfsResolution, type Tier, broadcastAlephMessage, broadcastInstanceMessage, createAlephBrowserClient, fetchBalance, fetchCrns, fetchInstancePricing, fetchInstances, fetchMessageEnvelope, fetchWithTimeout, inspectDeploymentResult, loadRootfsManifest, normalizeMessageStatus, parseInstancePricing, resolveRootfsReference, validateRootfsManifest, verifyRootfsExists, waitForDeploymentResult };
282
+ export { type AlephBroadcastMessage, type AlephBroadcastResponse, type AlephBrowserClient, type AlephMessageEnvelope, type AlephMessageType, type AlephSenderChain, type AllocationNotifyResult, BROWSER_PACKAGE_PLAN, type BalanceResponse, type BroadcastResult, type BrowserExtractionPhase, type BrowserPackagePlan, type ComputeUnit, type CreateAlephBrowserClientOptions, type Crn, type CrnListResponse, type CrnLocation, type CrnUsage, DEFAULT_ALEPH_AGGREGATE_ADDRESS, DEFAULT_ALEPH_API_HOST, DEFAULT_ALEPH_SCHEDULER_API_HOST, DEFAULT_CRN_LIST_URL, DEFAULT_IPFS_GATEWAY_BASE_URL, DEFAULT_ROOTFS_MANIFEST_URL, type DeploymentInspectionResult, type GatewayProbeStatus, ITEM_HASH_RE, type InstanceAllocation, type InstanceAllocationNode, type InstanceAllocationPeriod, type InstanceMessage, type InstancePricing, type LoadRootfsManifestOptions, type MessageReference, type MessageStatus, type PaymentMode, type Price, type PricingState, type ReferenceStatus, type RootfsManifest, type RootfsManifestState, type RootfsRequiredPortForward, type RootfsResolution, type Tier, broadcastAlephMessage, broadcastInstanceMessage, createAlephBrowserClient, fetchBalance, fetchCrns, fetchInstancePricing, fetchInstances, fetchMessageEnvelope, fetchSchedulerAllocation, fetchWithTimeout, inspectDeploymentResult, loadRootfsManifest, normalizeMessageStatus, notifyCrnAllocation, parseInstancePricing, resolveRootfsReference, validateRootfsManifest, verifyRootfsExists, waitForDeploymentResult };
package/index.js CHANGED
@@ -50,6 +50,7 @@ async function fetchWithTimeout(input, init = {}, timeoutMs = 15e3) {
50
50
  // src/aleph-api.ts
51
51
  var DEFAULT_ALEPH_API_HOST = "https://api2.aleph.im";
52
52
  var DEFAULT_CRN_LIST_URL = "https://crns-list.aleph.sh/crns.json";
53
+ var DEFAULT_ALEPH_SCHEDULER_API_HOST = "https://scheduler.api.aleph.cloud";
53
54
  function normalizeMessageStatus(status) {
54
55
  if (typeof status !== "string") return "unknown";
55
56
  const normalized = status.toLowerCase();
@@ -58,6 +59,16 @@ function normalizeMessageStatus(status) {
58
59
  }
59
60
  return "unknown";
60
61
  }
62
+ function asString(value) {
63
+ return typeof value === "string" && value.trim() ? value : null;
64
+ }
65
+ function asNumber(value) {
66
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
67
+ }
68
+ function isUnconfirmedNetworkError(error) {
69
+ const message = error instanceof Error ? error.message : String(error);
70
+ return error instanceof TypeError || message.includes("Failed to fetch") || message.includes("Request timed out");
71
+ }
61
72
  async function fetchBalance(address, apiHost = DEFAULT_ALEPH_API_HOST) {
62
73
  const response = await fetchWithTimeout(`${apiHost}/api/v0/addresses/${address}/balance`, {
63
74
  cache: "no-cache"
@@ -89,6 +100,53 @@ async function fetchInstances(address, apiHost = DEFAULT_ALEPH_API_HOST) {
89
100
  status: typeof message.status === "string" && message.status.trim() ? message.status : message.confirmed ? "processed" : message.status
90
101
  }));
91
102
  }
103
+ async function fetchSchedulerAllocation(itemHash, schedulerApiHost = DEFAULT_ALEPH_SCHEDULER_API_HOST) {
104
+ const response = await fetchWithTimeout(`${schedulerApiHost}/api/v0/allocation/${itemHash}`, {
105
+ cache: "no-cache"
106
+ });
107
+ if (response.status === 404) return null;
108
+ if (!response.ok) throw new Error(`Scheduler allocation request failed: ${response.status}`);
109
+ const payload = await response.json();
110
+ const node = payload.node;
111
+ return {
112
+ source: "scheduler",
113
+ crnUrl: asString(node?.url),
114
+ node: node ? {
115
+ node_id: asString(node.node_id) ?? void 0,
116
+ url: asString(node.url) ?? void 0,
117
+ ipv6: asString(node.ipv6),
118
+ supports_ipv6: typeof node.supports_ipv6 === "boolean" ? node.supports_ipv6 : void 0
119
+ } : null,
120
+ vmIpv6: asString(payload.vm_ipv6),
121
+ period: payload.period ? {
122
+ start_timestamp: asString(payload.period.start_timestamp) ?? void 0,
123
+ duration_seconds: asNumber(payload.period.duration_seconds) ?? void 0
124
+ } : null
125
+ };
126
+ }
127
+ async function notifyCrnAllocation(crnUrl, itemHash) {
128
+ const normalizedCrnUrl = crnUrl.replace(/\/+$/, "");
129
+ try {
130
+ const response = await fetchWithTimeout(`${normalizedCrnUrl}/control/allocation/notify`, {
131
+ method: "POST",
132
+ headers: {
133
+ "content-type": "text/plain;charset=UTF-8"
134
+ },
135
+ body: JSON.stringify({ instance: itemHash }),
136
+ mode: "cors"
137
+ });
138
+ if (!response.ok) {
139
+ const responseText = await response.text().catch(() => "");
140
+ throw new Error(`CRN allocation notify failed: ${response.status}${responseText ? ` ${responseText}` : ""}`);
141
+ }
142
+ return { status: "confirmed" };
143
+ } catch (error) {
144
+ if (isUnconfirmedNetworkError(error)) {
145
+ return { status: "unconfirmed" };
146
+ }
147
+ throw error;
148
+ }
149
+ }
92
150
  function messageTypeFromEnvelope(payload) {
93
151
  if (!payload) return null;
94
152
  const type = payload.type ?? payload.message?.type ?? (Array.isArray(payload.messages) ? payload.messages[0]?.type : void 0);
@@ -229,9 +287,11 @@ async function broadcastAlephMessage(message, apiHost = DEFAULT_ALEPH_API_HOST,
229
287
  function createAlephBrowserClient(options = {}) {
230
288
  const apiHost = options.apiHost ?? DEFAULT_ALEPH_API_HOST;
231
289
  const crnListUrl = options.crnListUrl ?? DEFAULT_CRN_LIST_URL;
290
+ const schedulerApiHost = options.schedulerApiHost ?? DEFAULT_ALEPH_SCHEDULER_API_HOST;
232
291
  return {
233
292
  apiHost,
234
293
  crnListUrl,
294
+ schedulerApiHost,
235
295
  fetchBalance(address) {
236
296
  return fetchBalance(address, apiHost);
237
297
  },
@@ -244,6 +304,12 @@ function createAlephBrowserClient(options = {}) {
244
304
  fetchMessageEnvelope(itemHash) {
245
305
  return fetchMessageEnvelope(itemHash, apiHost);
246
306
  },
307
+ fetchSchedulerAllocation(itemHash) {
308
+ return fetchSchedulerAllocation(itemHash, schedulerApiHost);
309
+ },
310
+ notifyCrnAllocation(crnUrl, itemHash) {
311
+ return notifyCrnAllocation(crnUrl, itemHash);
312
+ },
247
313
  inspectDeploymentResult(itemHash, rootfsRef) {
248
314
  return inspectDeploymentResult(itemHash, rootfsRef, apiHost);
249
315
  },
@@ -472,6 +538,7 @@ export {
472
538
  BROWSER_PACKAGE_PLAN,
473
539
  DEFAULT_ALEPH_AGGREGATE_ADDRESS,
474
540
  DEFAULT_ALEPH_API_HOST,
541
+ DEFAULT_ALEPH_SCHEDULER_API_HOST,
475
542
  DEFAULT_CRN_LIST_URL,
476
543
  DEFAULT_IPFS_GATEWAY_BASE_URL,
477
544
  DEFAULT_ROOTFS_MANIFEST_URL,
@@ -484,10 +551,12 @@ export {
484
551
  fetchInstancePricing,
485
552
  fetchInstances,
486
553
  fetchMessageEnvelope,
554
+ fetchSchedulerAllocation,
487
555
  fetchWithTimeout,
488
556
  inspectDeploymentResult,
489
557
  loadRootfsManifest,
490
558
  normalizeMessageStatus,
559
+ notifyCrnAllocation,
491
560
  parseInstancePricing,
492
561
  resolveRootfsReference,
493
562
  validateRootfsManifest,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@le-space/browser",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "description": "Shared browser-safe Aleph deployment and polling helpers.",
5
5
  "license": "MIT",
6
6
  "type": "module",