@le-space/browser 0.1.25 → 0.1.26
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/index.d.ts +30 -1
- package/index.js +96 -1
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ interface BrowserPackagePlan {
|
|
|
5
5
|
}
|
|
6
6
|
declare const BROWSER_PACKAGE_PLAN: BrowserPackagePlan;
|
|
7
7
|
type MessageStatus = 'processed' | 'pending' | 'rejected' | 'unknown';
|
|
8
|
+
type ReferenceStatus = MessageStatus | 'missing';
|
|
8
9
|
interface BalanceResponse {
|
|
9
10
|
address: string;
|
|
10
11
|
balance: string;
|
|
@@ -115,6 +116,31 @@ interface InstanceMessage {
|
|
|
115
116
|
confirmed?: boolean;
|
|
116
117
|
status?: string;
|
|
117
118
|
}
|
|
119
|
+
interface AlephMessageEnvelope {
|
|
120
|
+
status?: unknown;
|
|
121
|
+
type?: unknown;
|
|
122
|
+
error_code?: unknown;
|
|
123
|
+
details?: unknown;
|
|
124
|
+
message?: {
|
|
125
|
+
type?: unknown;
|
|
126
|
+
} | null;
|
|
127
|
+
messages?: Array<{
|
|
128
|
+
type?: unknown;
|
|
129
|
+
}> | null;
|
|
130
|
+
[key: string]: unknown;
|
|
131
|
+
}
|
|
132
|
+
interface MessageReference {
|
|
133
|
+
itemHash: string;
|
|
134
|
+
status: ReferenceStatus;
|
|
135
|
+
type: string | null;
|
|
136
|
+
}
|
|
137
|
+
interface DeploymentInspectionResult {
|
|
138
|
+
status: MessageStatus;
|
|
139
|
+
errorCode: number | null;
|
|
140
|
+
details: Record<string, unknown> | null;
|
|
141
|
+
rejectionReason: string | null;
|
|
142
|
+
references: MessageReference[];
|
|
143
|
+
}
|
|
118
144
|
interface RootfsRequiredPortForward {
|
|
119
145
|
port: number;
|
|
120
146
|
tcp?: boolean;
|
|
@@ -161,6 +187,9 @@ declare function normalizeMessageStatus(status: unknown): MessageStatus;
|
|
|
161
187
|
declare function fetchBalance(address: string, apiHost?: string): Promise<BalanceResponse>;
|
|
162
188
|
declare function fetchCrns(url?: string): Promise<Crn[]>;
|
|
163
189
|
declare function fetchInstances(address: string, apiHost?: string): Promise<InstanceMessage[]>;
|
|
190
|
+
declare function fetchMessageEnvelope(itemHash: string, apiHost?: string): Promise<AlephMessageEnvelope | null>;
|
|
191
|
+
declare function inspectDeploymentResult(itemHash: string, rootfsRef?: string, apiHost?: string): Promise<DeploymentInspectionResult>;
|
|
192
|
+
declare function waitForDeploymentResult(itemHash: string, rootfsRef?: string, apiHost?: string, attempts?: number, delayMs?: number): Promise<DeploymentInspectionResult>;
|
|
164
193
|
|
|
165
194
|
declare const ITEM_HASH_RE: RegExp;
|
|
166
195
|
declare const DEFAULT_ROOTFS_MANIFEST_URL = "./rootfs-manifest.json";
|
|
@@ -177,4 +206,4 @@ declare const DEFAULT_ALEPH_AGGREGATE_ADDRESS = "0xFba561a84A537fCaa567bb7A2257e
|
|
|
177
206
|
declare function parseInstancePricing(payload: unknown): InstancePricing;
|
|
178
207
|
declare function fetchInstancePricing(apiHost?: string, aggregateAddress?: string): Promise<PricingState>;
|
|
179
208
|
|
|
180
|
-
export { BROWSER_PACKAGE_PLAN, type BalanceResponse, type BrowserExtractionPhase, type BrowserPackagePlan, type ComputeUnit, 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 GatewayProbeStatus, ITEM_HASH_RE, type InstanceMessage, type InstancePricing, type LoadRootfsManifestOptions, type MessageStatus, type PaymentMode, type Price, type PricingState, type RootfsManifest, type RootfsManifestState, type RootfsRequiredPortForward, type RootfsResolution, type Tier, fetchBalance, fetchCrns, fetchInstancePricing, fetchInstances, fetchWithTimeout, loadRootfsManifest, normalizeMessageStatus, parseInstancePricing, resolveRootfsReference, validateRootfsManifest, verifyRootfsExists };
|
|
209
|
+
export { type AlephMessageEnvelope, BROWSER_PACKAGE_PLAN, type BalanceResponse, type BrowserExtractionPhase, type BrowserPackagePlan, type ComputeUnit, 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, fetchBalance, fetchCrns, fetchInstancePricing, fetchInstances, fetchMessageEnvelope, fetchWithTimeout, inspectDeploymentResult, loadRootfsManifest, normalizeMessageStatus, parseInstancePricing, resolveRootfsReference, validateRootfsManifest, verifyRootfsExists, waitForDeploymentResult };
|
package/index.js
CHANGED
|
@@ -89,6 +89,98 @@ async function fetchInstances(address, apiHost = DEFAULT_ALEPH_API_HOST) {
|
|
|
89
89
|
status: typeof message.status === "string" && message.status.trim() ? message.status : message.confirmed ? "processed" : message.status
|
|
90
90
|
}));
|
|
91
91
|
}
|
|
92
|
+
function messageTypeFromEnvelope(payload) {
|
|
93
|
+
if (!payload) return null;
|
|
94
|
+
const type = payload.type ?? payload.message?.type ?? (Array.isArray(payload.messages) ? payload.messages[0]?.type : void 0);
|
|
95
|
+
return typeof type === "string" ? type.toUpperCase() : null;
|
|
96
|
+
}
|
|
97
|
+
function extractReferenceHashes(details) {
|
|
98
|
+
if (!details || typeof details !== "object" || !("errors" in details)) return [];
|
|
99
|
+
const errors = details.errors;
|
|
100
|
+
if (!Array.isArray(errors)) return [];
|
|
101
|
+
return errors.filter((value) => typeof value === "string");
|
|
102
|
+
}
|
|
103
|
+
function describeRejectedDeployment(payload, references, rootfsRef) {
|
|
104
|
+
const errorCode = typeof payload.error_code === "number" ? payload.error_code : null;
|
|
105
|
+
const pendingReferences = references.filter((reference) => reference.status === "pending");
|
|
106
|
+
const missingReferences = references.filter((reference) => reference.status === "missing");
|
|
107
|
+
const rootfsReference = references.find((reference) => reference.itemHash === rootfsRef);
|
|
108
|
+
if (rootfsReference?.status === "pending") {
|
|
109
|
+
return `Aleph rejected this deployment because the referenced rootfs STORE message ${rootfsReference.itemHash} is still pending and cannot yet be used by an instance. Wait for that STORE message to process, then deploy again.`;
|
|
110
|
+
}
|
|
111
|
+
if (pendingReferences.length > 0) {
|
|
112
|
+
return `Aleph rejected this deployment because referenced message(s) are still pending: ${pendingReferences.map((reference) => reference.itemHash).join(", ")}.`;
|
|
113
|
+
}
|
|
114
|
+
if (missingReferences.length > 0) {
|
|
115
|
+
return `Aleph rejected this deployment because referenced message(s) were not found on Aleph: ${missingReferences.map((reference) => reference.itemHash).join(", ")}.`;
|
|
116
|
+
}
|
|
117
|
+
const referencedHashes = extractReferenceHashes(payload.details);
|
|
118
|
+
if (referencedHashes.length > 0) {
|
|
119
|
+
return `Aleph rejected this deployment${errorCode ? ` (error ${errorCode})` : ""}. Referenced message(s): ${referencedHashes.join(", ")}.`;
|
|
120
|
+
}
|
|
121
|
+
return `Aleph rejected this deployment${errorCode ? ` (error ${errorCode})` : ""}.`;
|
|
122
|
+
}
|
|
123
|
+
async function fetchMessageEnvelope(itemHash, apiHost = DEFAULT_ALEPH_API_HOST) {
|
|
124
|
+
const response = await fetchWithTimeout(`${apiHost}/api/v0/messages/${itemHash}`, {
|
|
125
|
+
cache: "no-cache"
|
|
126
|
+
});
|
|
127
|
+
if (response.status === 404) return null;
|
|
128
|
+
if (!response.ok) throw new Error(`Message lookup failed: ${response.status}`);
|
|
129
|
+
return await response.json();
|
|
130
|
+
}
|
|
131
|
+
async function fetchReference(itemHash, apiHost) {
|
|
132
|
+
const payload = await fetchMessageEnvelope(itemHash, apiHost);
|
|
133
|
+
if (!payload) {
|
|
134
|
+
return {
|
|
135
|
+
itemHash,
|
|
136
|
+
status: "missing",
|
|
137
|
+
type: null
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
itemHash,
|
|
142
|
+
status: normalizeMessageStatus(payload.status),
|
|
143
|
+
type: messageTypeFromEnvelope(payload)
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
async function inspectDeploymentResult(itemHash, rootfsRef, apiHost = DEFAULT_ALEPH_API_HOST) {
|
|
147
|
+
const payload = await fetchMessageEnvelope(itemHash, apiHost);
|
|
148
|
+
if (!payload) {
|
|
149
|
+
return {
|
|
150
|
+
status: "unknown",
|
|
151
|
+
errorCode: null,
|
|
152
|
+
details: null,
|
|
153
|
+
rejectionReason: `Deployment message ${itemHash} was not found on Aleph.`,
|
|
154
|
+
references: []
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const relatedHashes = new Set(rootfsRef ? [rootfsRef] : []);
|
|
158
|
+
for (const referenceHash of extractReferenceHashes(payload.details)) {
|
|
159
|
+
relatedHashes.add(referenceHash);
|
|
160
|
+
}
|
|
161
|
+
const references = await Promise.all(Array.from(relatedHashes).map((hash) => fetchReference(hash, apiHost)));
|
|
162
|
+
const status = normalizeMessageStatus(payload.status);
|
|
163
|
+
const errorCode = typeof payload.error_code === "number" ? payload.error_code : null;
|
|
164
|
+
const details = payload.details && typeof payload.details === "object" ? payload.details : null;
|
|
165
|
+
return {
|
|
166
|
+
status,
|
|
167
|
+
errorCode,
|
|
168
|
+
details,
|
|
169
|
+
rejectionReason: status === "rejected" ? describeRejectedDeployment(payload, references, rootfsRef) : null,
|
|
170
|
+
references
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async function waitForDeploymentResult(itemHash, rootfsRef, apiHost = DEFAULT_ALEPH_API_HOST, attempts = 15, delayMs = 2e3) {
|
|
174
|
+
let lastResult = await inspectDeploymentResult(itemHash, rootfsRef, apiHost);
|
|
175
|
+
for (let attempt = 1; attempt < attempts; attempt += 1) {
|
|
176
|
+
if (lastResult.status === "processed" || lastResult.status === "rejected") {
|
|
177
|
+
return lastResult;
|
|
178
|
+
}
|
|
179
|
+
await new Promise((resolve) => globalThis.setTimeout(resolve, delayMs));
|
|
180
|
+
lastResult = await inspectDeploymentResult(itemHash, rootfsRef, apiHost);
|
|
181
|
+
}
|
|
182
|
+
return lastResult;
|
|
183
|
+
}
|
|
92
184
|
|
|
93
185
|
// src/rootfs.ts
|
|
94
186
|
var ITEM_HASH_RE = /^[a-fA-F0-9]{64}$/u;
|
|
@@ -311,11 +403,14 @@ export {
|
|
|
311
403
|
fetchCrns,
|
|
312
404
|
fetchInstancePricing,
|
|
313
405
|
fetchInstances,
|
|
406
|
+
fetchMessageEnvelope,
|
|
314
407
|
fetchWithTimeout,
|
|
408
|
+
inspectDeploymentResult,
|
|
315
409
|
loadRootfsManifest,
|
|
316
410
|
normalizeMessageStatus,
|
|
317
411
|
parseInstancePricing,
|
|
318
412
|
resolveRootfsReference,
|
|
319
413
|
validateRootfsManifest,
|
|
320
|
-
verifyRootfsExists
|
|
414
|
+
verifyRootfsExists,
|
|
415
|
+
waitForDeploymentResult
|
|
321
416
|
};
|