tabulark 0.0.4 → 0.2.1
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/CHANGELOG.md +81 -0
- package/README.md +316 -128
- package/THIRD_PARTY_NOTICES.md +37 -0
- package/dist/adapters.d.ts +62 -0
- package/dist/arrow.d.ts +3 -0
- package/dist/arrow.js +2 -0
- package/dist/arrow.js.map +7 -0
- package/dist/client.d.ts +145 -0
- package/dist/errors.d.ts +25 -0
- package/dist/excel.d.ts +3 -0
- package/dist/excel.js +2 -0
- package/dist/excel.js.map +7 -0
- package/dist/experimental.d.ts +13 -0
- package/dist/experimental.js +2 -0
- package/dist/experimental.js.map +7 -0
- package/dist/http.d.ts +65 -0
- package/dist/http.js +2 -0
- package/dist/http.js.map +7 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +7 -0
- package/dist/model.d.ts +392 -0
- package/dist/official-adapter-manifest.d.ts +31 -0
- package/dist/parquet.d.ts +3 -0
- package/dist/parquet.js +2 -0
- package/dist/parquet.js.map +7 -0
- package/dist/protocol.d.ts +54 -0
- package/dist/range-cache.d.ts +47 -0
- package/dist/range-source.d.ts +64 -0
- package/dist/rpc-client.d.ts +31 -0
- package/dist/source.d.ts +13 -0
- package/dist/view/accessible-grid.d.ts +36 -0
- package/dist/view/canvas-painter.d.ts +91 -0
- package/dist/view/canvas-table-view-public.d.ts +64 -0
- package/dist/view/canvas-table-view.d.ts +40 -0
- package/dist/view/controller.d.ts +34 -0
- package/dist/view/layout.d.ts +34 -0
- package/dist/view/selection.d.ts +7 -0
- package/dist/view/types.d.ts +184 -0
- package/dist/wasm/arrow/tabulark_arrow.d.ts +153 -0
- package/dist/wasm/arrow/tabulark_arrow.js +883 -0
- package/dist/wasm/arrow/tabulark_arrow_bg.wasm +0 -0
- package/dist/wasm/arrow/tabulark_arrow_bg.wasm.d.ts +30 -0
- package/dist/wasm/delimited/tabulark_delimited.d.ts +157 -0
- package/dist/wasm/delimited/tabulark_delimited.js +952 -0
- package/dist/wasm/delimited/tabulark_delimited_bg.wasm +0 -0
- package/dist/wasm/delimited/tabulark_delimited_bg.wasm.d.ts +31 -0
- package/dist/wasm/excel/tabulark_excel.d.ts +146 -0
- package/dist/wasm/excel/tabulark_excel.js +876 -0
- package/dist/wasm/excel/tabulark_excel_bg.wasm +0 -0
- package/dist/wasm/excel/tabulark_excel_bg.wasm.d.ts +30 -0
- package/dist/wasm/parquet/tabulark_parquet.d.ts +146 -0
- package/dist/wasm/parquet/tabulark_parquet.js +872 -0
- package/dist/wasm/parquet/tabulark_parquet_bg.wasm +0 -0
- package/dist/wasm/parquet/tabulark_parquet_bg.wasm.d.ts +30 -0
- package/dist/worker/blob-source-accessor.d.ts +10 -0
- package/dist/worker/source-accessor.d.ts +76 -0
- package/dist/worker/wasm-adapter.d.ts +58 -0
- package/dist/worker/worker-errors.d.ts +9 -0
- package/dist/worker-range-source.d.ts +1 -0
- package/dist/worker-range-source.js +2 -0
- package/dist/worker-range-source.js.map +7 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +2 -0
- package/dist/worker.js.map +7 -0
- package/package.json +62 -12
- package/js/index.d.ts +0 -18
- package/js/index.js +0 -26
package/dist/http.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var TabularkError=class _TabularkError extends Error{code;retryable;details;constructor(code,message,options={}){super(message,{cause:options.cause});this.name="TabularkError";this.code=code;this.retryable=options.retryable??false;this.details=code==="RESOURCE_LIMIT"?normalizeResourceLimitDetails(options.details):options.details}static fromSerialized(error){return new _TabularkError(error.code,error.message,{retryable:error.retryable,details:error.details})}};function normalizeResourceLimitDetails(details){const raw=isRecord(details)?details:{};const resource=typeof raw.resource==="string"&&raw.resource.length>0?raw.resource:typeof raw.resourceCategory==="string"&&raw.resourceCategory.length>0?raw.resourceCategory:inferResource(raw);if(isQuantity(raw.requiredBytes)&&isQuantity(raw.availableBytes)){return Object.freeze({...raw,resource})}if(isQuantity(raw.required)&&isQuantity(raw.available)){return Object.freeze({...raw,resource})}const byteLimit=firstQuantity(raw,["maxDecodedBytes","maxOutputBytes","maxMetadataBytes","maxBlockBytes","maxDisplayCellBytes","maxDisplayBytes","maxSourceBytes","maxFieldBytes","maxBatchBytes","maxOperationBytes","maxZipEntryBytes","maxZipUncompressedBytes","maxCfbStreamBytes"]);if(byteLimit!==void 0){const requiredBytes=firstQuantity(raw,["decodedBytes","outputBytes","metadataBytes","blockBytes","displayCellBytes","displayBytes","sourceBytes","fieldBytes","batchBytes","operationBytes"])??byteLimit+1;return Object.freeze({...raw,resource,requiredBytes,availableBytes:byteLimit})}const available=firstQuantity(raw,["limit","maxCells","maxRangeCells","maxSources","maxActiveRanges","maxRangeWaiters","maxColumns","maxFields","maxNestingDepth","maxWorksheetRows","maxWorksheetColumns","maxStyles","maxMergedRegions"])??0;const required=firstQuantity(raw,["cells","cellCount","visibleCellCount","sources","activeRanges","rangeWaiters","columns","fields","nestingDepth","worksheetRows","worksheetColumns","styles","mergedRegions"])??available+1;return Object.freeze({...raw,resource,required,available})}function inferResource(details){const keys=Object.keys(details).join(" ").toLowerCase();if(keys.includes("source"))return keys.includes("byte")?"source-staging":"source-slots";if(keys.includes("metadata"))return"metadata";if(keys.includes("decoded")||keys.includes("decompress"))return"decompression";if(keys.includes("display"))return"display-values";if(keys.includes("field"))return"field";if(keys.includes("batch"))return"batch";if(keys.includes("range")||keys.includes("cell"))return"range-cells";if(keys.includes("column"))return"columns";if(keys.includes("nest"))return"descriptor-nesting";if(keys.includes("worksheet"))return"worksheet-dimensions";return"adapter-resource"}function firstQuantity(details,names){for(const name of names){if(isQuantity(details[name]))return details[name]}return void 0}function isQuantity(value){return typeof value==="number"&&Number.isFinite(value)&&value>=0}function isRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function cancelledError(){return new TabularkError("CANCELLED","The operation was cancelled")}function closedError(resource){return new TabularkError("HANDLE_CLOSED",`${resource} is closed`)}function invalidArgument(message,details){return new TabularkError("INVALID_ARGUMENT",message,{details})}var MAX_RANGE_SOURCE_BYTES=4294967295;function validateByteRange(range,size){if(!isSafeNonNegativeInteger(size)||size>MAX_RANGE_SOURCE_BYTES){throw new RangeError("source size is outside the supported range")}if(typeof range!=="object"||range===null){throw new RangeError("range must be an object")}const candidate=range;let offset;let length;try{offset=candidate.offset;length=candidate.length}catch{throw new RangeError("range is outside the source")}if(!isSafeNonNegativeInteger(offset)||!isSafeNonNegativeInteger(length)||offset>MAX_RANGE_SOURCE_BYTES||length>MAX_RANGE_SOURCE_BYTES||offset+length>size){throw new RangeError("range is outside the source")}}function copyRangeBytes(value){if(value instanceof ArrayBuffer)return value.slice(0);if(!ArrayBuffer.isView(value)){throw new RangeError("reader returned a non-buffer value")}const bytes=new Uint8Array(value.buffer,value.byteOffset,value.byteLength);const copy=new Uint8Array(bytes.byteLength);copy.set(bytes);return copy.buffer}function isSafeNonNegativeInteger(value){return typeof value==="number"&&Number.isSafeInteger(value)&&value>=0}var RETRYABLE_STATUSES=new Set([408,425,429,500,502,503,504]);var DEFAULT_ATTEMPTS=3;var MAX_ATTEMPTS=8;var INITIAL_BACKOFF_MS=100;var MAX_BACKOFF_MS=1e3;var MAX_RETRY_AFTER_MS=5e3;var MAX_VALIDATOR_LENGTH=4096;var RANGE_SOURCE_HOST_RESERVATION_STORE=Symbol.for("tabulark.internal.range-source-reservation-store.v1");function rangeSourceHostReservations(options){try{const host=globalThis;const value=host[RANGE_SOURCE_HOST_RESERVATION_STORE]?.get(options);if(typeof value!=="object"||value===null)return void 0;const candidate=value;return typeof candidate.reserveStaging==="function"&&typeof candidate.reserveRetained==="function"?candidate:void 0}catch{return void 0}}function httpRangeSource(url,options={}){if(typeof url!=="string"&&!(typeof URL!=="undefined"&&url instanceof URL)||String(url).length===0){throw invalidArgument("HTTP source URL must be a non-empty string")}const requestUrl=String(url);const normalized=normalizeOptions(options);const source={kind:"range",...normalized.name===void 0?{}:{name:normalized.name},open:openOptions=>openHttpReader(requestUrl,normalized,openOptions)};return Object.freeze(source)}async function openHttpReader(url,options,openOptions){validateOpenOptions(openOptions);const openSignal=openOptions.signal;const maxSourceBytes=openOptions.maxSourceBytes;const maxStagingBytes=openOptions.maxStagingBytes;const hostReservations=rangeSourceHostReservations(openOptions);if(openSignal.aborted)throw cancelledError();const probeController=linkAbortSignal(openSignal);try{return await requestWithRetry(url,options,{phase:"probe",signal:probeController.controller.signal},async response=>{if(response.status===206){const parsed=parseContentRange(response,0,1);if(parsed===void 0){throw sourceError("RANGE_UNSUPPORTED","The source returned an invalid byte range")}const size=parsed.total;assertSourceSize(size,maxSourceBytes);const validator=selectValidator(response,size,options.validation);await readOpenResponseBody(response,1,probeController.controller.signal,hostReservations);const snapshot=createSnapshot(validator,size);return new HttpReader(url,options,size,snapshot,validator,maxStagingBytes,void 0,void 0)}if(response.status===416&&parseUnsatisfiedContentRange(response)===0){assertSourceSize(0,maxSourceBytes);const validator=selectValidator(response,0,options.validation);try{await response.body?.cancel()}catch{}const snapshot=createSnapshot(validator,0);return new HttpReader(url,options,0,snapshot,validator,maxStagingBytes,void 0,void 0)}if(response.status===200&&options.fallback?.mode==="bounded-download"){const contentLength=parseContentLength(response);if(contentLength===void 0){throw sourceError("RANGE_UNSUPPORTED","The source does not provide a bounded length")}assertSourceSize(contentLength,maxSourceBytes);const bound=Math.min(options.fallback.maxBytes,maxStagingBytes);if(contentLength>bound){throw resourceLimitError(contentLength,bound,"source-staging")}const validator=selectValidator(response,contentLength,options.validation);let releaseStaging;let releaseRetained;let bytes;try{releaseStaging=await hostReservations?.reserveStaging(contentLength,probeController.controller.signal);releaseRetained=hostReservations?.reserveRetained(contentLength);bytes=await readResponseBody(response,contentLength,probeController.controller.signal)}catch(error){releaseRetained?.();throw error}finally{releaseStaging?.()}const snapshot=createSnapshot(validator,contentLength);return new HttpReader(url,options,contentLength,snapshot,validator,maxStagingBytes,bytes,releaseRetained)}if(response.status===416||response.status===200){throw sourceError("RANGE_UNSUPPORTED","The source does not support byte ranges")}throw responseError(response.status)})}catch(error){throw normalizeHttpError(error,"Unable to open the source")}finally{probeController.dispose()}}var HttpReader=class{size;snapshot;maxConcurrency;#closed=false;#fallbackBytes;#releaseRetained;#url;#options;#validator;#maxReadBytes;#closeController=new AbortController;#limiter;constructor(url,options,size,snapshot,validator,maxReadBytes,fallbackBytes,releaseRetained){this.#url=url;this.#options=options;this.size=size;this.snapshot=Object.freeze({...snapshot});this.#validator=validator;this.#maxReadBytes=maxReadBytes;this.#fallbackBytes=fallbackBytes;this.#releaseRetained=releaseRetained;this.maxConcurrency=options.maxConcurrency;this.#limiter=new ReadLimiter(this.maxConcurrency)}async read(range,options){if(this.#closed)throw closedError("Range source reader");if(typeof options!=="object"||options===null||!isAbortSignal(options.signal)){throw invalidArgument("range read options must include an AbortSignal")}let requestedRange;try{if(typeof range!=="object"||range===null)throw new RangeError;requestedRange=Object.freeze({offset:range.offset,length:range.length});validateByteRange(requestedRange,this.size)}catch{throw sourceError("RANGE_UNSUPPORTED","The requested source range is outside the source")}if(options.signal.aborted)throw cancelledError();if(requestedRange.length===0)return new ArrayBuffer(0);if(requestedRange.length>this.#maxReadBytes){throw resourceLimitError(requestedRange.length,this.#maxReadBytes,"source-staging")}const signal=combineSignals(this.#closeController.signal,options.signal);const release=await this.#limiter.acquire(signal);try{if(this.#closed)throw closedError("Range source reader");if(signal.aborted)throw cancelledError();if(this.#fallbackBytes!==void 0){const view=new Uint8Array(this.#fallbackBytes,requestedRange.offset,requestedRange.length);return copyRangeBytes(view)}return await requestWithRetry(this.#url,this.#options,{phase:"read",range:requestedRange,signal},async response=>{if(response.status===200||response.status===416){throw sourceError("RANGE_UNSUPPORTED","The source stopped supporting byte ranges")}if(response.status!==206)throw responseError(response.status);const parsed=parseContentRange(response,requestedRange.offset,requestedRange.length);if(parsed===void 0){throw sourceError("RANGE_UNSUPPORTED","The source returned an invalid byte range")}if(parsed.total!==this.size){throw sourceError("SOURCE_CHANGED","The source changed while it was open")}validateValidator(response,this.#validator,this.size);return readResponseBody(response,requestedRange.length,signal)})}catch(error){if(this.#closed)throw closedError("Range source reader");throw normalizeHttpError(error,"Unable to read the source")}finally{release()}}close(){if(this.#closed)return;this.#closed=true;this.#limiter.close();this.#closeController.abort();this.#fallbackBytes=void 0;this.#releaseRetained?.();this.#releaseRetained=void 0}};function normalizeOptions(options){if(typeof options!=="object"||options===null||Array.isArray(options)){throw invalidArgument("HTTP source options must be an object")}const maxConcurrency=options.maxConcurrency??1;if(!isSafeNonNegativeInteger(maxConcurrency)||maxConcurrency<1||maxConcurrency>4){throw invalidArgument("HTTP source maxConcurrency must be an integer from 1 to 4")}const validation=options.validation??options.validator??"strong";if(validation!=="strong"&&validation!=="weak"&&validation!=="etag"&&validation!=="last-modified"){throw invalidArgument("HTTP source validation strength is invalid")}if(options.credentials!==void 0&&options.credentials!=="omit"&&options.credentials!=="same-origin"&&options.credentials!=="include"){throw invalidArgument("HTTP source credentials are invalid")}const sourceName=options.name??options.sourceName;if(sourceName!==void 0&&(typeof sourceName!=="string"||sourceName.length>256)){throw invalidArgument("HTTP source name is invalid")}if(options.fetch!==void 0&&typeof options.fetch!=="function"){throw invalidArgument("HTTP source fetch must be a function")}if(options.getHeaders!==void 0&&typeof options.getHeaders!=="function"){throw invalidArgument("HTTP source getHeaders must be a function")}if(options.retry!==void 0&&(typeof options.retry!=="object"||options.retry===null||Array.isArray(options.retry))){throw invalidArgument("HTTP source retry options are invalid")}let maxAttempts=options.maxAttempts;if(maxAttempts===void 0){maxAttempts=options.retry?.maxAttempts??options.retry?.attempts}if(maxAttempts===void 0){const retries=options.retry?.maxRetries??options.maxRetries??options.retries;maxAttempts=retries===void 0?DEFAULT_ATTEMPTS:retries+1}if(!isSafeNonNegativeInteger(maxAttempts)||maxAttempts<1||maxAttempts>MAX_ATTEMPTS){throw invalidArgument("HTTP source retry attempts are outside the supported range")}if(options.fallback!==void 0){if(typeof options.fallback!=="object"||options.fallback===null||options.fallback.mode!=="bounded-download"||!isSafeNonNegativeInteger(options.fallback.maxBytes)||options.fallback.maxBytes>MAX_RANGE_SOURCE_BYTES){throw invalidArgument("HTTP source fallback is invalid")}}const fetchImpl=options.fetch!==void 0?options.fetch.bind(globalThis):typeof globalThis.fetch==="function"?globalThis.fetch.bind(globalThis):void 0;if(fetchImpl===void 0){throw new TabularkError("UNSUPPORTED_RUNTIME","HTTP sources require fetch support")}let staticHeaders;if(options.headers!==void 0){if(typeof options.headers==="function"){staticHeaders=options.headers}else{try{staticHeaders=new Headers(options.headers)}catch{throw invalidArgument("HTTP source headers are invalid")}}}return Object.freeze({...staticHeaders===void 0?{}:{headers:staticHeaders},...options.getHeaders===void 0?{}:{getHeaders:options.getHeaders},...options.credentials===void 0?{}:{credentials:options.credentials},fetch:fetchImpl,validation,maxConcurrency,maxAttempts,...options.fallback===void 0?{}:{fallback:Object.freeze({...options.fallback})},retryBaseDelayMs:normalizeDelay(options.retry?.baseDelayMs,INITIAL_BACKOFF_MS),retryMaxDelayMs:normalizeDelay(options.retry?.maxDelayMs,MAX_BACKOFF_MS),...sourceName===void 0?{}:{name:sourceName}})}function normalizeDelay(value,fallback){if(value===void 0)return fallback;if(!Number.isFinite(value)||value<0){throw invalidArgument("HTTP source retry delay is invalid")}return Math.min(MAX_BACKOFF_MS,Math.floor(value))}function validateOpenOptions(options){if(typeof options!=="object"||options===null||!isAbortSignal(options.signal)){throw invalidArgument("Range source open options must include an AbortSignal")}if(!isSafeNonNegativeInteger(options.maxSourceBytes)||!isSafeNonNegativeInteger(options.maxStagingBytes)){throw invalidArgument("Range source limits must be safe non-negative integers")}if(options.maxStagingBytes===0){throw resourceLimitError(1,0,"source-staging")}}function assertSourceSize(size,maxSourceBytes){if(!isSafeNonNegativeInteger(size)||size>MAX_RANGE_SOURCE_BYTES){throw resourceLimitError(size,MAX_RANGE_SOURCE_BYTES,"source-address-space")}if(size>maxSourceBytes){throw resourceLimitError(size,maxSourceBytes,"source-staging")}}async function requestWithRetry(url,options,context,consume){const stableContext=Object.freeze({phase:context.phase,signal:context.signal,...context.range===void 0?{}:{range:Object.freeze({offset:context.range.offset,length:context.range.length})}});for(let attempt=0;attempt<options.maxAttempts;attempt+=1){if(stableContext.signal.aborted)throw cancelledError();const headers=await resolveHeaders(options,stableContext);let response;try{if(stableContext.signal.aborted)throw cancelledError();const requestHeaders=new Headers(headers);if(stableContext.range===void 0){requestHeaders.set("Range","bytes=0-0")}else{const end=stableContext.range.offset+stableContext.range.length-1;requestHeaders.set("Range",`bytes=${stableContext.range.offset}-${end}`)}response=await options.fetch(url,{method:"GET",headers:requestHeaders,...options.credentials===void 0?{}:{credentials:options.credentials},signal:stableContext.signal})}catch(error){if(stableContext.signal.aborted||isAbortLike(error))throw cancelledError();if(attempt+1>=options.maxAttempts){throw sourceError("SOURCE_UNAVAILABLE","The source could not be reached",true)}await retryDelay(void 0,attempt,stableContext.signal,options);continue}if(response.status===0&&attempt+1<options.maxAttempts){try{await response.body?.cancel()}catch{}await retryDelay(void 0,attempt,stableContext.signal,options);continue}if(RETRYABLE_STATUSES.has(response.status)&&attempt+1<options.maxAttempts){try{await response.body?.cancel()}catch{}await retryDelay(response,attempt,stableContext.signal,options);continue}if(RETRYABLE_STATUSES.has(response.status)){try{await response.body?.cancel()}catch{}throw sourceError("SOURCE_UNAVAILABLE","The source returned a temporary failure",true,{status:response.status})}if(response.status===0){try{await response.body?.cancel()}catch{}throw sourceError("SOURCE_UNAVAILABLE","The source returned an unavailable response",true)}try{return await consume(response)}catch(error){try{await response.body?.cancel()}catch{}if(!(error instanceof RetryableBodyError))throw error;if(stableContext.signal.aborted)throw cancelledError();if(attempt+1>=options.maxAttempts){throw sourceError("SOURCE_UNAVAILABLE","The source body could not be read",true)}await retryDelay(void 0,attempt,stableContext.signal,options)}}throw sourceError("SOURCE_UNAVAILABLE","The source could not be reached",true)}async function resolveHeaders(options,context){try{let value;if(typeof options.headers==="function"){value=await options.headers(context)}else{value=options.headers}if(options.getHeaders!==void 0){const dynamic=await options.getHeaders(context);value=mergeHeaders(value,dynamic)}return new Headers(value)}catch(error){if(context.signal.aborted)throw cancelledError();throw sourceError("SOURCE_UNAVAILABLE","The source request headers could not be prepared")}}function mergeHeaders(first,second){const merged=new Headers(first);new Headers(second).forEach((value,key)=>merged.set(key,value));return merged}function parseContentRange(response,expectedOffset,expectedLength){const value=responseHeader(response,"Content-Range");if(value===void 0)return void 0;const match=/^bytes ([0-9]+)-([0-9]+)\/([0-9]+)$/u.exec(value.trim());if(!match)return void 0;const start=Number(match[1]);const end=Number(match[2]);const total=Number(match[3]);if(!isSafeNonNegativeInteger(start)||!isSafeNonNegativeInteger(end)||!isSafeNonNegativeInteger(total)||start!==expectedOffset||end<start||end-start+1!==expectedLength||end>=total){return void 0}return{total}}function parseContentLength(response){const value=responseHeader(response,"Content-Length");if(value===void 0||!/^[0-9]+$/u.test(value.trim()))return void 0;const length=Number(value.trim());return isSafeNonNegativeInteger(length)?length:void 0}function parseUnsatisfiedContentRange(response){const value=responseHeader(response,"Content-Range");if(value===void 0)return void 0;const match=/^bytes \*\/([0-9]+)$/u.exec(value.trim());if(!match)return void 0;const total=Number(match[1]);return isSafeNonNegativeInteger(total)?total:void 0}function selectValidator(response,size,strength){const etag=responseHeader(response,"ETag")?.trim();const validEtag=etag!==void 0&&etag.length<=MAX_VALIDATOR_LENGTH&&/^(?:W\/)?"[\x21\x23-\x7e\x80-\xff]*"$/u.test(etag)&&(strength==="weak"||strength==="last-modified"||!etag.startsWith("W/"));if(strength==="etag"&&!validEtag){throw sourceError("SOURCE_UNAVAILABLE","The source has no usable ETag validator")}if(validEtag){if(strength==="last-modified"){}else{return Object.freeze({kind:"etag",value:etag,strength:etag.startsWith("W/")?"weak":"strong"})}}const lastModified=responseHeader(response,"Last-Modified")?.trim();if(lastModified!==void 0&&lastModified.length>0&&lastModified.length<=MAX_VALIDATOR_LENGTH&&isHttpDate(lastModified)){return Object.freeze({kind:"last-modified",value:`${lastModified}|${size}`,strength:"weak"})}throw sourceError("SOURCE_UNAVAILABLE","The source has no usable validator")}function isHttpDate(value){const day="(?:0[1-9]|[12][0-9]|3[01])";const month="(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)";const time="(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]";const weekday="(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)";const longWeekday="(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)";const imf=new RegExp(`^${weekday}, ${day} ${month} [0-9]{4} ${time} GMT$`,"u");const rfc850=new RegExp(`^${longWeekday}, ${day}-${month}-[0-9]{2} ${time} GMT$`,"u");const asctime=new RegExp(`^${weekday} ${month} (?: [1-9]|[12][0-9]|3[01]) ${time} [0-9]{4}$`,"u");return(imf.test(value)||rfc850.test(value)||asctime.test(value))&&Number.isFinite(Date.parse(value))}function validateValidator(response,validator,size){if(validator.kind==="etag"){const current2=responseHeader(response,"ETag")?.trim();if(current2===void 0||current2!==validator.value){throw sourceError("SOURCE_CHANGED","The source changed while it was open")}return}const current=responseHeader(response,"Last-Modified")?.trim();if(current===void 0||`${current}|${size}`!==validator.value){throw sourceError("SOURCE_CHANGED","The source changed while it was open")}}function createSnapshot(validator,size){const id=`http-${hashOpaque(`${validator.kind}\0${validator.value}\0${size}`)}`;return Object.freeze({id,strength:validator.strength})}function hashOpaque(value){let hash=0xcbf29ce484222325n;for(let index=0;index<value.length;index+=1){hash^=BigInt(value.charCodeAt(index));hash=BigInt.asUintN(64,hash*0x100000001b3n)}return hash.toString(16).padStart(16,"0")}async function readOpenResponseBody(response,expectedLength,signal,reservations){const release=await reservations?.reserveStaging(expectedLength,signal);try{return await readResponseBody(response,expectedLength,signal)}finally{release?.()}}var RetryableBodyError=class extends Error{constructor(cause){super("The source response body transport failed",{cause});this.name="RetryableBodyError"}};async function readResponseBody(response,expectedLength,signal){if(signal.aborted)throw cancelledError();const rawContentLength=responseHeader(response,"Content-Length");if(rawContentLength!==void 0&&parseContentLength(response)===void 0){throw sourceError("SOURCE_UNAVAILABLE","The source returned an invalid byte length")}const contentLength=parseContentLength(response);if(contentLength!==void 0&&contentLength!==expectedLength){throw sourceError("SOURCE_UNAVAILABLE","The source returned an unexpected byte length",false,{expectedBytes:expectedLength,actualBytes:contentLength})}const body=response.body;if(body!==null&&body!==void 0&&typeof body.getReader==="function"){const reader=body.getReader();const output=new Uint8Array(expectedLength);let offset=0;const onAbort=()=>{void Promise.resolve(reader.cancel()).catch(()=>{})};signal.addEventListener("abort",onAbort,{once:true});try{while(offset<expectedLength){if(signal.aborted)throw cancelledError();const result=await readResponseChunk(reader,signal);if(result.done)break;const chunk=toUint8Array(result.value);if(offset+chunk.byteLength>expectedLength){throw sourceError("SOURCE_UNAVAILABLE","The source returned too many bytes",false,{expectedBytes:expectedLength,actualBytes:offset+chunk.byteLength})}output.set(chunk,offset);offset+=chunk.byteLength}if(offset!==expectedLength){throw sourceError("SOURCE_UNAVAILABLE","The source returned too few bytes",false,{expectedBytes:expectedLength,actualBytes:offset})}const extra=await readResponseChunk(reader,signal);if(!extra.done){const extraLength=toUint8Array(extra.value).byteLength;try{await reader.cancel()}catch{}throw sourceError("SOURCE_UNAVAILABLE","The source returned too many bytes",false,{expectedBytes:expectedLength,actualBytes:expectedLength+extraLength})}return output.buffer}catch(error){try{await reader.cancel()}catch{}if(signal.aborted||isAbortLike(error))throw cancelledError();throw error}finally{signal.removeEventListener("abort",onAbort);try{reader.releaseLock()}catch{}}}if(typeof response.arrayBuffer!=="function"){throw sourceError("SOURCE_UNAVAILABLE","The source returned no readable body")}let rawValue;try{rawValue=await response.arrayBuffer()}catch(error){if(signal.aborted||isAbortLike(error))throw cancelledError();throw new RetryableBodyError(error)}if(signal.aborted)throw cancelledError();let value;try{value=copyRangeBytes(rawValue)}catch{throw sourceError("SOURCE_UNAVAILABLE","The source returned an invalid body")}if(value.byteLength!==expectedLength){throw sourceError("SOURCE_UNAVAILABLE","The source returned an unexpected byte length",false,{expectedBytes:expectedLength,actualBytes:value.byteLength})}return value}async function readResponseChunk(reader,signal){try{return await reader.read()}catch(error){if(signal.aborted||isAbortLike(error))throw cancelledError();throw new RetryableBodyError(error)}}function toUint8Array(value){if(value instanceof Uint8Array)return value;if(value instanceof ArrayBuffer)return new Uint8Array(value);if(ArrayBuffer.isView(value)){return new Uint8Array(value.buffer,value.byteOffset,value.byteLength)}throw sourceError("SOURCE_UNAVAILABLE","The source returned an invalid body")}function responseHeader(response,name){const headers=response.headers;if(headers!==void 0&&headers!==null&&typeof headers.get==="function"){const value=headers.get(name);return value===null?void 0:value}const raw=headers;if(raw===void 0||raw===null)return void 0;for(const key of Object.keys(raw)){if(key.toLowerCase()===name.toLowerCase()&&typeof raw[key]==="string"){return raw[key]}}return void 0}function responseError(status){return sourceError("SOURCE_UNAVAILABLE","The source returned an unavailable response",false,{...Number.isSafeInteger(status)&&status>=0?{status}:{}})}function sourceError(code,message,retryable=false,details){return new TabularkError(code,message,{retryable,...details===void 0?{}:{details}})}function resourceLimitError(requiredBytes,availableBytes,resource){return new TabularkError("RESOURCE_LIMIT","The source exceeds its configured limit",{details:{resource,requiredBytes,availableBytes}})}function normalizeHttpError(error,fallbackMessage){const structured=tabularkErrorLike(error);if(structured!==void 0){if(structured.code==="SOURCE_UNAVAILABLE"||structured.code==="SOURCE_CHANGED"||structured.code==="RANGE_UNSUPPORTED"||structured.code==="RESOURCE_LIMIT"||structured.code==="CANCELLED"||structured.code==="HANDLE_CLOSED"){if(structured.code==="RESOURCE_LIMIT"){return new TabularkError("RESOURCE_LIMIT","The source exceeds its configured limit",{details:isSafeLimitDetails(structured.details)})}if(structured.code==="CANCELLED")return cancelledError();if(structured.code==="HANDLE_CLOSED")return closedError("Range source reader");return sourceError(structured.code,sourceErrorMessage(structured.code),structured.retryable,safeSourceDetails(structured.details))}return sourceError("SOURCE_UNAVAILABLE",fallbackMessage,true)}if(isAbortLike(error))return cancelledError();return sourceError("SOURCE_UNAVAILABLE",fallbackMessage,true)}function tabularkErrorLike(value){if(typeof value!=="object"||value===null||Array.isArray(value))return void 0;try{const candidate=value;if(typeof candidate.code!=="string"||typeof candidate.retryable!=="boolean"){return void 0}return{code:candidate.code,retryable:candidate.retryable,details:candidate.details}}catch{return void 0}}function isSafeLimitDetails(value){if(typeof value!=="object"||value===null||Array.isArray(value)){return{resource:"source-staging",requiredBytes:0,availableBytes:0}}const raw=value;const resource=typeof raw.resource==="string"&&/^[A-Za-z0-9_.:-]{1,64}$/u.test(raw.resource)?raw.resource:"source-staging";const requiredBytes=isSafeNonNegativeInteger(raw.requiredBytes)?raw.requiredBytes:0;const availableBytes=isSafeNonNegativeInteger(raw.availableBytes)?raw.availableBytes:0;return{resource,requiredBytes,availableBytes}}function safeSourceDetails(value){if(typeof value!=="object"||value===null||Array.isArray(value))return void 0;const raw=value;const details={};for(const key of["status","expectedBytes","actualBytes"]){if(isSafeNonNegativeInteger(raw[key]))details[key]=raw[key]}return Object.keys(details).length===0?void 0:details}function sourceErrorMessage(code){switch(code){case"SOURCE_CHANGED":return"The source changed while it was open";case"RANGE_UNSUPPORTED":return"The source does not support the requested range";default:return"The source is unavailable"}}function isAbortLike(error){return typeof error==="object"&&error!==null&&(error.name==="AbortError"||error.code===20)}async function retryDelay(response,attempt,signal,options){const retryAfter=response===void 0?void 0:parseRetryAfter(response);const base=retryAfter??Math.min(options.retryMaxDelayMs,options.retryBaseDelayMs*2**attempt);const jittered=retryAfter===void 0?Math.max(0,Math.min(options.retryMaxDelayMs,Math.round(base*(.5+Math.random())))):Math.min(MAX_RETRY_AFTER_MS,base);if(jittered<=0)return;await new Promise((resolve,reject)=>{if(signal.aborted){reject(cancelledError());return}const timer=setTimeout(done,jittered);const onAbort=()=>{clearTimeout(timer);signal.removeEventListener("abort",onAbort);reject(cancelledError())};function done(){signal.removeEventListener("abort",onAbort);resolve()}signal.addEventListener("abort",onAbort,{once:true})})}function parseRetryAfter(response){const value=responseHeader(response,"Retry-After")?.trim();if(value===void 0||value.length===0)return void 0;if(/^[0-9]+$/u.test(value)){return Math.min(MAX_RETRY_AFTER_MS,Number(value)*1e3)}const timestamp=Date.parse(value);if(!Number.isFinite(timestamp))return void 0;return Math.min(MAX_RETRY_AFTER_MS,Math.max(0,timestamp-Date.now()))}function isAbortSignal(value){return typeof value==="object"&&value!==null&&typeof value.aborted==="boolean"&&typeof value.addEventListener==="function"}function linkAbortSignal(signal){const controller=new AbortController;const onAbort=()=>controller.abort();if(signal.aborted)controller.abort();signal.addEventListener("abort",onAbort,{once:true});return{controller,dispose:()=>signal.removeEventListener("abort",onAbort)}}function combineSignals(first,second){if(first===second)return first;const any=AbortSignal.any;if(typeof any==="function")return any([first,second]);const controller=new AbortController;const abort=()=>controller.abort();if(first.aborted||second.aborted)controller.abort();else{first.addEventListener("abort",abort,{once:true});second.addEventListener("abort",abort,{once:true})}return controller.signal}var ReadLimiter=class{#active=0;#closed=false;#limit;#queue=[];constructor(limit){this.#limit=limit}acquire(signal){if(this.#closed)return Promise.reject(closedError("Range source reader"));if(signal.aborted)return Promise.reject(cancelledError());if(this.#active<this.#limit){this.#active+=1;return Promise.resolve(()=>this.release())}return new Promise((resolve,reject)=>{const entry={resolve,reject,signal,onAbort:()=>void 0};const onAbort=()=>{const index=this.#queue.indexOf(entry);if(index>=0)this.#queue.splice(index,1);signal.removeEventListener("abort",onAbort);reject(cancelledError())};entry.onAbort=onAbort;signal.addEventListener("abort",onAbort,{once:true});this.#queue.push(entry)})}close(){if(this.#closed)return;this.#closed=true;for(const entry of this.#queue.splice(0)){entry.signal.removeEventListener("abort",entry.onAbort);entry.reject(closedError("Range source reader"))}}release(){this.#active=Math.max(0,this.#active-1);if(this.#closed)return;const next=this.#queue.shift();if(next===void 0)return;next.signal.removeEventListener("abort",next.onAbort);if(next.signal.aborted){next.reject(cancelledError());this.release();return}this.#active+=1;next.resolve(()=>this.release())}};export{httpRangeSource};
|
|
2
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../js/errors.ts", "../js/range-source.ts", "../js/http.ts"],
|
|
4
|
+
"sourcesContent": ["import type { SerializedError } from \"./protocol.js\";\n\nexport type TabularkErrorCode =\n | \"INVALID_ARGUMENT\"\n | \"INVALID_RANGE\"\n | \"RANGE_NOT_INDEXED\"\n | \"RESOURCE_LIMIT\"\n | \"CANCELLED\"\n | \"HANDLE_CLOSED\"\n | \"PROTOCOL_INCOMPATIBLE\"\n | \"PARSE_FAILED\"\n | \"UNSUPPORTED_FEATURE\"\n | \"UNSUPPORTED_RUNTIME\"\n | \"RUNTIME_FAILURE\"\n /** A remote/source provider could not be reached or did not return bytes. */\n | \"SOURCE_UNAVAILABLE\"\n /** The provider validator or total length changed while a reader was open. */\n | \"SOURCE_CHANGED\"\n /** The provider did not honor the required single-range protocol. */\n | \"RANGE_UNSUPPORTED\"\n | (string & {});\n\n/** A stable, serializable error returned by Tabulark. */\nexport class TabularkError extends Error {\n readonly code: TabularkErrorCode;\n readonly retryable: boolean;\n readonly details?: unknown;\n\n constructor(\n code: TabularkErrorCode,\n message: string,\n options: { retryable?: boolean; details?: unknown; cause?: unknown } = {},\n ) {\n super(message, { cause: options.cause });\n this.name = \"TabularkError\";\n this.code = code;\n this.retryable = options.retryable ?? false;\n this.details = code === \"RESOURCE_LIMIT\"\n ? normalizeResourceLimitDetails(options.details)\n : options.details;\n }\n\n static fromSerialized(error: SerializedError): TabularkError {\n return new TabularkError(error.code, error.message, {\n retryable: error.retryable,\n details: error.details,\n });\n }\n}\n\n/** @internal Ensures every resource-limit error has a stable capacity shape. */\nexport function normalizeResourceLimitDetails(details: unknown): Readonly<Record<string, unknown>> {\n const raw = isRecord(details) ? details : {};\n const resource = typeof raw.resource === \"string\" && raw.resource.length > 0\n ? raw.resource\n : typeof raw.resourceCategory === \"string\" && raw.resourceCategory.length > 0\n ? raw.resourceCategory\n : inferResource(raw);\n if (isQuantity(raw.requiredBytes) && isQuantity(raw.availableBytes)) {\n return Object.freeze({ ...raw, resource });\n }\n if (isQuantity(raw.required) && isQuantity(raw.available)) {\n return Object.freeze({ ...raw, resource });\n }\n\n const byteLimit = firstQuantity(raw, [\n \"maxDecodedBytes\",\n \"maxOutputBytes\",\n \"maxMetadataBytes\",\n \"maxBlockBytes\",\n \"maxDisplayCellBytes\",\n \"maxDisplayBytes\",\n \"maxSourceBytes\",\n \"maxFieldBytes\",\n \"maxBatchBytes\",\n \"maxOperationBytes\",\n \"maxZipEntryBytes\",\n \"maxZipUncompressedBytes\",\n \"maxCfbStreamBytes\",\n ]);\n if (byteLimit !== undefined) {\n const requiredBytes = firstQuantity(raw, [\n \"decodedBytes\",\n \"outputBytes\",\n \"metadataBytes\",\n \"blockBytes\",\n \"displayCellBytes\",\n \"displayBytes\",\n \"sourceBytes\",\n \"fieldBytes\",\n \"batchBytes\",\n \"operationBytes\",\n ]) ?? byteLimit + 1;\n return Object.freeze({\n ...raw,\n resource,\n requiredBytes,\n availableBytes: byteLimit,\n });\n }\n\n const available = firstQuantity(raw, [\n \"limit\",\n \"maxCells\",\n \"maxRangeCells\",\n \"maxSources\",\n \"maxActiveRanges\",\n \"maxRangeWaiters\",\n \"maxColumns\",\n \"maxFields\",\n \"maxNestingDepth\",\n \"maxWorksheetRows\",\n \"maxWorksheetColumns\",\n \"maxStyles\",\n \"maxMergedRegions\",\n ]) ?? 0;\n const required = firstQuantity(raw, [\n \"cells\",\n \"cellCount\",\n \"visibleCellCount\",\n \"sources\",\n \"activeRanges\",\n \"rangeWaiters\",\n \"columns\",\n \"fields\",\n \"nestingDepth\",\n \"worksheetRows\",\n \"worksheetColumns\",\n \"styles\",\n \"mergedRegions\",\n ]) ?? available + 1;\n return Object.freeze({ ...raw, resource, required, available });\n}\n\nfunction inferResource(details: Record<string, unknown>): string {\n const keys = Object.keys(details).join(\" \").toLowerCase();\n if (keys.includes(\"source\")) return keys.includes(\"byte\") ? \"source-staging\" : \"source-slots\";\n if (keys.includes(\"metadata\")) return \"metadata\";\n if (keys.includes(\"decoded\") || keys.includes(\"decompress\")) return \"decompression\";\n if (keys.includes(\"display\")) return \"display-values\";\n if (keys.includes(\"field\")) return \"field\";\n if (keys.includes(\"batch\")) return \"batch\";\n if (keys.includes(\"range\") || keys.includes(\"cell\")) return \"range-cells\";\n if (keys.includes(\"column\")) return \"columns\";\n if (keys.includes(\"nest\")) return \"descriptor-nesting\";\n if (keys.includes(\"worksheet\")) return \"worksheet-dimensions\";\n return \"adapter-resource\";\n}\n\nfunction firstQuantity(\n details: Record<string, unknown>,\n names: readonly string[],\n): number | undefined {\n for (const name of names) {\n if (isQuantity(details[name])) return details[name] as number;\n }\n return undefined;\n}\n\nfunction isQuantity(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value >= 0;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function cancelledError(): TabularkError {\n return new TabularkError(\"CANCELLED\", \"The operation was cancelled\");\n}\n\nexport function closedError(resource: string): TabularkError {\n return new TabularkError(\"HANDLE_CLOSED\", `${resource} is closed`);\n}\n\nexport function invalidArgument(message: string, details?: unknown): TabularkError {\n return new TabularkError(\"INVALID_ARGUMENT\", message, { details });\n}\n", "/**\n * Bounded, repeatable byte-range sources.\n *\n * A RangeSource is intentionally a very small host-side capability. The\n * worker never receives the implementation (or a URL); it is given an opaque\n * reader handle by the client and asks the host for bounded byte ranges.\n */\n\n/** The largest addressable source (2^32 - 1 bytes). */\nexport const MAX_RANGE_SOURCE_BYTES = 0xffff_ffff;\n\n/** A half-open byte interval [offset, offset + length). */\nexport interface ByteRange {\n readonly offset: number;\n readonly length: number;\n}\n\n/** A stable identity for one opened view of a source. */\nexport interface RangeSourceSnapshot {\n readonly id: string;\n readonly strength: \"strong\" | \"weak\";\n}\n\n/** Options supplied to every reader operation. */\nexport interface RangeSourceReadOptions {\n readonly signal: AbortSignal;\n}\n\n/** A reader returned by a RangeSource.open() call. */\nexport interface RangeSourceReader {\n /** Exact source size in bytes. */\n readonly size: number;\n /** Validator captured while opening the source. */\n readonly snapshot: RangeSourceSnapshot;\n /** Maximum number of provider reads that may run concurrently. Defaults to 1. */\n readonly maxConcurrency?: number;\n /** Reads exactly range.length bytes, or rejects. */\n read(\n range: ByteRange,\n options: RangeSourceReadOptions,\n ): Promise<ArrayBuffer | ArrayBufferView>;\n /** Releases all resources. Calling close more than once is harmless. */\n close(): Promise<void> | void;\n}\n\n/** Open-time limits owned by the engine. */\nexport interface RangeSourceOpenOptions {\n readonly signal: AbortSignal;\n readonly maxSourceBytes: number;\n readonly maxStagingBytes: number;\n}\n\n/** A repeatably openable source addressed by bounded byte ranges. */\nexport interface RangeSource {\n readonly kind: \"range\";\n readonly name?: string;\n open(options: RangeSourceOpenOptions): Promise<RangeSourceReader>;\n}\n\n/** Runtime check used at the public engine boundary. */\nexport function isRangeSource(value: unknown): value is RangeSource {\n if (typeof value !== \"object\" || value === null) return false;\n try {\n const candidate = value as { kind?: unknown; open?: unknown };\n return candidate.kind === \"range\" && typeof candidate.open === \"function\";\n } catch {\n return false;\n }\n}\n\n/**\n * Validates a byte range without coercing values. Keeping this check in one\n * place prevents unsafe floating-point arithmetic at both HTTP and Worker\n * boundaries.\n */\nexport function validateByteRange(\n range: unknown,\n size: number,\n): asserts range is ByteRange {\n if (!isSafeNonNegativeInteger(size) || size > MAX_RANGE_SOURCE_BYTES) {\n throw new RangeError(\"source size is outside the supported range\");\n }\n if (typeof range !== \"object\" || range === null) {\n throw new RangeError(\"range must be an object\");\n }\n const candidate = range as { offset?: unknown; length?: unknown };\n let offset: unknown;\n let length: unknown;\n try {\n offset = candidate.offset;\n length = candidate.length;\n } catch {\n throw new RangeError(\"range is outside the source\");\n }\n if (!isSafeNonNegativeInteger(offset)\n || !isSafeNonNegativeInteger(length)\n || offset > MAX_RANGE_SOURCE_BYTES\n || length > MAX_RANGE_SOURCE_BYTES\n || offset + length > size) {\n throw new RangeError(\"range is outside the source\");\n }\n}\n\n/** Validates and freezes a reader snapshot. */\nexport function normalizeRangeSourceSnapshot(value: unknown): RangeSourceSnapshot {\n if (typeof value !== \"object\" || value === null) {\n throw new RangeError(\"reader snapshot must be an object\");\n }\n const candidate = value as { id?: unknown; strength?: unknown };\n if (typeof candidate.id !== \"string\"\n || candidate.id.length === 0\n || candidate.id.length > 256\n || candidate.strength !== \"strong\" && candidate.strength !== \"weak\") {\n throw new RangeError(\"reader snapshot is invalid\");\n }\n return Object.freeze({ id: candidate.id, strength: candidate.strength });\n}\n\n/** Validates a reader object returned by an adapter/broker. */\nexport function validateRangeSourceReader(value: unknown): value is RangeSourceReader {\n if (typeof value !== \"object\" || value === null) return false;\n try {\n const candidate = value as {\n size?: unknown;\n snapshot?: unknown;\n maxConcurrency?: unknown;\n read?: unknown;\n close?: unknown;\n };\n if (!isSafeNonNegativeInteger(candidate.size)\n || candidate.size > MAX_RANGE_SOURCE_BYTES\n || !isValidSnapshot(candidate.snapshot)\n || typeof candidate.read !== \"function\"\n || typeof candidate.close !== \"function\") {\n return false;\n }\n return candidate.maxConcurrency === undefined\n || (isSafeNonNegativeInteger(candidate.maxConcurrency)\n && candidate.maxConcurrency >= 1\n && candidate.maxConcurrency <= 4);\n } catch {\n // A hostile proxy/getter is an invalid reader, not an unstructured host\n // exception that should escape the public open() contract.\n return false;\n }\n}\n\n/** Converts an ArrayBuffer or view to a fresh, exact-length ArrayBuffer. */\nexport function copyRangeBytes(value: ArrayBuffer | ArrayBufferView): ArrayBuffer {\n if (value instanceof ArrayBuffer) return value.slice(0);\n if (!ArrayBuffer.isView(value)) {\n throw new RangeError(\"reader returned a non-buffer value\");\n }\n const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return copy.buffer;\n}\n\n/** Returns whether a value is a safe non-negative integer. */\nexport function isSafeNonNegativeInteger(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction isValidSnapshot(value: unknown): value is RangeSourceSnapshot {\n if (typeof value !== \"object\" || value === null) return false;\n const candidate = value as { id?: unknown; strength?: unknown };\n return typeof candidate.id === \"string\"\n && candidate.id.length > 0\n && candidate.id.length <= 256\n && (candidate.strength === \"strong\" || candidate.strength === \"weak\");\n}\n", "import {\n TabularkError,\n cancelledError,\n closedError,\n invalidArgument,\n} from \"./errors.js\";\nimport {\n MAX_RANGE_SOURCE_BYTES,\n copyRangeBytes,\n isSafeNonNegativeInteger,\n validateByteRange,\n type ByteRange,\n type RangeSource,\n type RangeSourceOpenOptions,\n type RangeSourceReader,\n type RangeSourceSnapshot,\n} from \"./range-source.js\";\n\n/** The phase in which dynamic request headers are evaluated. */\nexport type HttpHeaderPhase = \"probe\" | \"read\";\n\nexport interface HttpHeaderContext {\n readonly phase: HttpHeaderPhase;\n readonly range?: ByteRange;\n readonly signal: AbortSignal;\n}\n\n/** Static headers or a per-request (for example, rotating-auth) provider. */\nexport type HttpHeaders = HeadersInit | ((context: HttpHeaderContext) =>\n HeadersInit | Promise<HeadersInit>);\n\nexport interface BoundedDownloadFallback {\n readonly mode: \"bounded-download\";\n /** Maximum full-response bytes the caller explicitly permits. */\n readonly maxBytes: number;\n}\n\nexport type HttpValidationStrength = \"strong\" | \"weak\" | \"etag\" | \"last-modified\";\n\n/** Optional retry spelling accepted by the HTTP helper. */\nexport interface HttpRetryOptions {\n /** Total attempts, including the first request. */\n readonly maxAttempts?: number;\n /** Alias for maxAttempts. */\n readonly attempts?: number;\n /** Attempts after the first request. */\n readonly maxRetries?: number;\n readonly baseDelayMs?: number;\n readonly maxDelayMs?: number;\n}\n\n/** Options for {@link httpRangeSource}. */\nexport interface HttpRangeSourceOptions {\n /** Static headers or a function evaluated for every probe/read attempt. */\n readonly headers?: HttpHeaders;\n /** Alias for callers that prefer an explicit dynamic-header name. */\n readonly getHeaders?: (context: HttpHeaderContext) =>\n HeadersInit | Promise<HeadersInit>;\n readonly credentials?: RequestCredentials;\n /** Injected fetch implementation, useful for SSR/tests. */\n readonly fetch?: HttpFetch;\n /** Defaults to strong ETag, with Last-Modified + length as a weak fallback. */\n readonly validation?: HttpValidationStrength;\n /** Compatibility alias for validation. */\n readonly validator?: HttpValidationStrength;\n /** Maximum simultaneous range reads (1\u20134, defaults to 1). */\n readonly maxConcurrency?: number;\n /** Number of retries after the first attempt (defaults to 2; 3 total attempts). */\n readonly retries?: number;\n readonly maxRetries?: number;\n readonly retry?: HttpRetryOptions;\n /** Explicit total-attempts spelling; takes precedence over retries. */\n readonly maxAttempts?: number;\n /** Explicitly permits a small full response when range requests are unavailable. */\n readonly fallback?: BoundedDownloadFallback;\n /** Optional logical display name. It is never sent in diagnostics. */\n readonly name?: string;\n /** Alias for name. */\n readonly sourceName?: string;\n}\n\n/** Fetch-compatible function accepted by the HTTP adapter. */\nexport type HttpFetch = (\n input: RequestInfo | URL,\n init?: RequestInit,\n) => Response | Promise<Response>;\n\nconst RETRYABLE_STATUSES = new Set([408, 425, 429, 500, 502, 503, 504]);\nconst DEFAULT_ATTEMPTS = 3;\nconst MAX_ATTEMPTS = 8;\nconst INITIAL_BACKOFF_MS = 100;\nconst MAX_BACKOFF_MS = 1_000;\nconst MAX_RETRY_AFTER_MS = 5_000;\nconst MAX_VALIDATOR_LENGTH = 4_096;\nconst RANGE_SOURCE_HOST_RESERVATION_STORE = Symbol.for(\n \"tabulark.internal.range-source-reservation-store.v1\",\n);\n\ninterface RangeSourceHostReservations {\n reserveStaging(bytes: number, signal: AbortSignal): Promise<() => void>;\n reserveRetained(bytes: number): () => void;\n}\n\nfunction rangeSourceHostReservations(\n options: RangeSourceOpenOptions,\n): RangeSourceHostReservations | undefined {\n try {\n const host = globalThis as typeof globalThis & {\n [RANGE_SOURCE_HOST_RESERVATION_STORE]?: WeakMap<object, unknown>;\n };\n const value = host[RANGE_SOURCE_HOST_RESERVATION_STORE]?.get(options);\n if (typeof value !== \"object\" || value === null) return undefined;\n const candidate = value as Partial<RangeSourceHostReservations>;\n return typeof candidate.reserveStaging === \"function\"\n && typeof candidate.reserveRetained === \"function\"\n ? candidate as RangeSourceHostReservations\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Creates a stable remote byte-range source.\n *\n * No request is made until `open()` is called. Each open performs an\n * independent capability probe and returns an independent reader, allowing a\n * source to be reopened after a dataset is closed.\n */\nexport function httpRangeSource(\n url: string | URL,\n options: HttpRangeSourceOptions = {},\n): RangeSource {\n if (\n (typeof url !== \"string\" && !(typeof URL !== \"undefined\" && url instanceof URL))\n || String(url).length === 0\n ) {\n throw invalidArgument(\"HTTP source URL must be a non-empty string\");\n }\n const requestUrl = String(url);\n const normalized = normalizeOptions(options);\n const source: RangeSource = {\n kind: \"range\",\n ...(normalized.name === undefined ? {} : { name: normalized.name }),\n open: (openOptions) => openHttpReader(requestUrl, normalized, openOptions),\n };\n return Object.freeze(source);\n}\n\ninterface NormalizedHttpOptions {\n readonly headers?: HttpHeaders;\n readonly getHeaders?: HttpRangeSourceOptions[\"getHeaders\"];\n readonly credentials?: RequestCredentials;\n readonly fetch: HttpFetch;\n readonly validation: HttpValidationStrength;\n readonly maxConcurrency: number;\n readonly maxAttempts: number;\n readonly retryBaseDelayMs: number;\n readonly retryMaxDelayMs: number;\n readonly fallback?: BoundedDownloadFallback;\n readonly name?: string;\n}\n\nasync function openHttpReader(\n url: string,\n options: NormalizedHttpOptions,\n openOptions: RangeSourceOpenOptions,\n): Promise<RangeSourceReader> {\n validateOpenOptions(openOptions);\n const openSignal = openOptions.signal;\n const maxSourceBytes = openOptions.maxSourceBytes;\n const maxStagingBytes = openOptions.maxStagingBytes;\n const hostReservations = rangeSourceHostReservations(openOptions);\n if (openSignal.aborted) throw cancelledError();\n\n const probeController = linkAbortSignal(openSignal);\n try {\n return await requestWithRetry(\n url,\n options,\n { phase: \"probe\", signal: probeController.controller.signal },\n async (response) => {\n if (response.status === 206) {\n const parsed = parseContentRange(response, 0, 1);\n if (parsed === undefined) {\n throw sourceError(\"RANGE_UNSUPPORTED\", \"The source returned an invalid byte range\");\n }\n const size = parsed.total;\n assertSourceSize(size, maxSourceBytes);\n const validator = selectValidator(response, size, options.validation);\n await readOpenResponseBody(\n response,\n 1,\n probeController.controller.signal,\n hostReservations,\n );\n const snapshot = createSnapshot(validator, size);\n return new HttpReader(\n url,\n options,\n size,\n snapshot,\n validator,\n maxStagingBytes,\n undefined,\n undefined,\n );\n }\n\n // An empty object cannot satisfy bytes=0-0. RFC 9110 represents that\n // one special case as 416 with `Content-Range: bytes */0`.\n if (response.status === 416 && parseUnsatisfiedContentRange(response) === 0) {\n assertSourceSize(0, maxSourceBytes);\n const validator = selectValidator(response, 0, options.validation);\n try { await response.body?.cancel(); } catch { /* best effort */ }\n const snapshot = createSnapshot(validator, 0);\n return new HttpReader(\n url,\n options,\n 0,\n snapshot,\n validator,\n maxStagingBytes,\n undefined,\n undefined,\n );\n }\n\n if (response.status === 200 && options.fallback?.mode === \"bounded-download\") {\n const contentLength = parseContentLength(response);\n if (contentLength === undefined) {\n throw sourceError(\"RANGE_UNSUPPORTED\", \"The source does not provide a bounded length\");\n }\n assertSourceSize(contentLength, maxSourceBytes);\n const bound = Math.min(options.fallback.maxBytes, maxStagingBytes);\n if (contentLength > bound) {\n throw resourceLimitError(contentLength, bound, \"source-staging\");\n }\n const validator = selectValidator(response, contentLength, options.validation);\n let releaseStaging: (() => void) | undefined;\n let releaseRetained: (() => void) | undefined;\n let bytes: ArrayBuffer;\n try {\n releaseStaging = await hostReservations?.reserveStaging(\n contentLength,\n probeController.controller.signal,\n );\n releaseRetained = hostReservations?.reserveRetained(contentLength);\n bytes = await readResponseBody(\n response,\n contentLength,\n probeController.controller.signal,\n );\n } catch (error) {\n releaseRetained?.();\n throw error;\n } finally {\n releaseStaging?.();\n }\n const snapshot = createSnapshot(validator, contentLength);\n return new HttpReader(\n url,\n options,\n contentLength,\n snapshot,\n validator,\n maxStagingBytes,\n bytes,\n releaseRetained,\n );\n }\n\n if (response.status === 416 || response.status === 200) {\n throw sourceError(\"RANGE_UNSUPPORTED\", \"The source does not support byte ranges\");\n }\n throw responseError(response.status);\n },\n );\n } catch (error) {\n throw normalizeHttpError(error, \"Unable to open the source\");\n } finally {\n probeController.dispose();\n }\n}\n\nclass HttpReader implements RangeSourceReader {\n readonly size: number;\n readonly snapshot: RangeSourceSnapshot;\n readonly maxConcurrency: number;\n #closed = false;\n #fallbackBytes: ArrayBuffer | undefined;\n #releaseRetained: (() => void) | undefined;\n readonly #url: string;\n readonly #options: NormalizedHttpOptions;\n readonly #validator: Validator;\n readonly #maxReadBytes: number;\n readonly #closeController = new AbortController();\n readonly #limiter: ReadLimiter;\n\n constructor(\n url: string,\n options: NormalizedHttpOptions,\n size: number,\n snapshot: RangeSourceSnapshot,\n validator: Validator,\n maxReadBytes: number,\n fallbackBytes: ArrayBuffer | undefined,\n releaseRetained: (() => void) | undefined,\n ) {\n this.#url = url;\n this.#options = options;\n this.size = size;\n this.snapshot = Object.freeze({ ...snapshot });\n this.#validator = validator;\n this.#maxReadBytes = maxReadBytes;\n this.#fallbackBytes = fallbackBytes;\n this.#releaseRetained = releaseRetained;\n this.maxConcurrency = options.maxConcurrency;\n this.#limiter = new ReadLimiter(this.maxConcurrency);\n }\n\n async read(\n range: ByteRange,\n options: { signal: AbortSignal },\n ): Promise<ArrayBuffer> {\n if (this.#closed) throw closedError(\"Range source reader\");\n if (typeof options !== \"object\" || options === null || !isAbortSignal(options.signal)) {\n throw invalidArgument(\"range read options must include an AbortSignal\");\n }\n let requestedRange: ByteRange;\n try {\n if (typeof range !== \"object\" || range === null) throw new RangeError();\n requestedRange = Object.freeze({\n offset: range.offset,\n length: range.length,\n });\n validateByteRange(requestedRange, this.size);\n } catch {\n // A malformed or out-of-bounds provider range is a structured source\n // failure at the public boundary; do not leak a native RangeError whose\n // shape differs between browsers.\n throw sourceError(\"RANGE_UNSUPPORTED\", \"The requested source range is outside the source\");\n }\n // The request can wait behind the reader limiter and user-supplied header\n // callbacks. Snapshot the structural input now so caller/callback mutation\n // cannot bypass the staging check or alter the authoritative Range header.\n if (options.signal.aborted) throw cancelledError();\n if (requestedRange.length === 0) return new ArrayBuffer(0);\n if (requestedRange.length > this.#maxReadBytes) {\n throw resourceLimitError(requestedRange.length, this.#maxReadBytes, \"source-staging\");\n }\n const signal = combineSignals(this.#closeController.signal, options.signal);\n const release = await this.#limiter.acquire(signal);\n try {\n if (this.#closed) throw closedError(\"Range source reader\");\n if (signal.aborted) throw cancelledError();\n if (this.#fallbackBytes !== undefined) {\n const view = new Uint8Array(\n this.#fallbackBytes,\n requestedRange.offset,\n requestedRange.length,\n );\n return copyRangeBytes(view);\n }\n return await requestWithRetry(\n this.#url,\n this.#options,\n { phase: \"read\", range: requestedRange, signal },\n async (response) => {\n if (response.status === 200 || response.status === 416) {\n throw sourceError(\"RANGE_UNSUPPORTED\", \"The source stopped supporting byte ranges\");\n }\n if (response.status !== 206) throw responseError(response.status);\n const parsed = parseContentRange(\n response,\n requestedRange.offset,\n requestedRange.length,\n );\n if (parsed === undefined) {\n throw sourceError(\"RANGE_UNSUPPORTED\", \"The source returned an invalid byte range\");\n }\n if (parsed.total !== this.size) {\n throw sourceError(\"SOURCE_CHANGED\", \"The source changed while it was open\");\n }\n validateValidator(response, this.#validator, this.size);\n return readResponseBody(response, requestedRange.length, signal);\n },\n );\n } catch (error) {\n if (this.#closed) throw closedError(\"Range source reader\");\n throw normalizeHttpError(error, \"Unable to read the source\");\n } finally {\n release();\n }\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n this.#limiter.close();\n this.#closeController.abort();\n this.#fallbackBytes = undefined;\n this.#releaseRetained?.();\n this.#releaseRetained = undefined;\n }\n}\n\ninterface Validator {\n readonly kind: \"etag\" | \"last-modified\";\n readonly value: string;\n readonly strength: \"strong\" | \"weak\";\n}\n\nfunction normalizeOptions(options: HttpRangeSourceOptions): NormalizedHttpOptions {\n if (typeof options !== \"object\" || options === null || Array.isArray(options)) {\n throw invalidArgument(\"HTTP source options must be an object\");\n }\n const maxConcurrency = options.maxConcurrency ?? 1;\n if (!isSafeNonNegativeInteger(maxConcurrency) || maxConcurrency < 1 || maxConcurrency > 4) {\n throw invalidArgument(\"HTTP source maxConcurrency must be an integer from 1 to 4\");\n }\n const validation = options.validation ?? options.validator ?? \"strong\";\n if (validation !== \"strong\" && validation !== \"weak\"\n && validation !== \"etag\" && validation !== \"last-modified\") {\n throw invalidArgument(\"HTTP source validation strength is invalid\");\n }\n if (options.credentials !== undefined\n && options.credentials !== \"omit\"\n && options.credentials !== \"same-origin\"\n && options.credentials !== \"include\") {\n throw invalidArgument(\"HTTP source credentials are invalid\");\n }\n const sourceName = options.name ?? options.sourceName;\n if (sourceName !== undefined\n && (typeof sourceName !== \"string\" || sourceName.length > 256)) {\n throw invalidArgument(\"HTTP source name is invalid\");\n }\n if (options.fetch !== undefined && typeof options.fetch !== \"function\") {\n throw invalidArgument(\"HTTP source fetch must be a function\");\n }\n if (options.getHeaders !== undefined && typeof options.getHeaders !== \"function\") {\n throw invalidArgument(\"HTTP source getHeaders must be a function\");\n }\n if (options.retry !== undefined\n && (typeof options.retry !== \"object\" || options.retry === null || Array.isArray(options.retry))) {\n throw invalidArgument(\"HTTP source retry options are invalid\");\n }\n let maxAttempts = options.maxAttempts;\n if (maxAttempts === undefined) {\n maxAttempts = options.retry?.maxAttempts ?? options.retry?.attempts;\n }\n if (maxAttempts === undefined) {\n const retries = options.retry?.maxRetries ?? options.maxRetries ?? options.retries;\n maxAttempts = retries === undefined ? DEFAULT_ATTEMPTS : retries + 1;\n }\n if (!isSafeNonNegativeInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > MAX_ATTEMPTS) {\n throw invalidArgument(\"HTTP source retry attempts are outside the supported range\");\n }\n if (options.fallback !== undefined) {\n if (typeof options.fallback !== \"object\" || options.fallback === null\n || options.fallback.mode !== \"bounded-download\"\n || !isSafeNonNegativeInteger(options.fallback.maxBytes)\n || options.fallback.maxBytes > MAX_RANGE_SOURCE_BYTES) {\n throw invalidArgument(\"HTTP source fallback is invalid\");\n }\n }\n const fetchImpl = options.fetch !== undefined\n ? options.fetch.bind(globalThis)\n : (typeof globalThis.fetch === \"function\" ? globalThis.fetch.bind(globalThis) : undefined);\n if (fetchImpl === undefined) {\n throw new TabularkError(\"UNSUPPORTED_RUNTIME\", \"HTTP sources require fetch support\");\n }\n let staticHeaders: HttpHeaders | undefined;\n if (options.headers !== undefined) {\n if (typeof options.headers === \"function\") {\n staticHeaders = options.headers;\n } else {\n try {\n staticHeaders = new Headers(options.headers);\n } catch {\n throw invalidArgument(\"HTTP source headers are invalid\");\n }\n }\n }\n return Object.freeze({\n ...(staticHeaders === undefined ? {} : { headers: staticHeaders }),\n ...(options.getHeaders === undefined ? {} : { getHeaders: options.getHeaders }),\n ...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n fetch: fetchImpl,\n validation,\n maxConcurrency,\n maxAttempts,\n ...(options.fallback === undefined ? {} : { fallback: Object.freeze({ ...options.fallback }) }),\n retryBaseDelayMs: normalizeDelay(options.retry?.baseDelayMs, INITIAL_BACKOFF_MS),\n retryMaxDelayMs: normalizeDelay(options.retry?.maxDelayMs, MAX_BACKOFF_MS),\n ...(sourceName === undefined ? {} : { name: sourceName }),\n });\n}\n\nfunction normalizeDelay(value: number | undefined, fallback: number): number {\n if (value === undefined) return fallback;\n if (!Number.isFinite(value) || value < 0) {\n throw invalidArgument(\"HTTP source retry delay is invalid\");\n }\n return Math.min(MAX_BACKOFF_MS, Math.floor(value));\n}\n\nfunction validateOpenOptions(options: RangeSourceOpenOptions): void {\n if (typeof options !== \"object\" || options === null || !isAbortSignal(options.signal)) {\n throw invalidArgument(\"Range source open options must include an AbortSignal\");\n }\n if (!isSafeNonNegativeInteger(options.maxSourceBytes)\n || !isSafeNonNegativeInteger(options.maxStagingBytes)) {\n throw invalidArgument(\"Range source limits must be safe non-negative integers\");\n }\n // A non-empty range probe itself needs one bounded byte. The engine always\n // supplies a positive staging slice, but rejecting an impossible direct\n // caller here keeps the provider contract structured and deterministic.\n if (options.maxStagingBytes === 0) {\n throw resourceLimitError(1, 0, \"source-staging\");\n }\n}\n\nfunction assertSourceSize(size: number, maxSourceBytes: number): void {\n if (!isSafeNonNegativeInteger(size) || size > MAX_RANGE_SOURCE_BYTES) {\n throw resourceLimitError(size, MAX_RANGE_SOURCE_BYTES, \"source-address-space\");\n }\n if (size > maxSourceBytes) {\n throw resourceLimitError(size, maxSourceBytes, \"source-staging\");\n }\n}\n\nasync function requestWithRetry<T>(\n url: string,\n options: NormalizedHttpOptions,\n context: HttpHeaderContext,\n consume: (response: Response) => Promise<T>,\n): Promise<T> {\n const stableContext: HttpHeaderContext = Object.freeze({\n phase: context.phase,\n signal: context.signal,\n ...(context.range === undefined\n ? {}\n : { range: Object.freeze({ offset: context.range.offset, length: context.range.length }) }),\n });\n for (let attempt = 0; attempt < options.maxAttempts; attempt += 1) {\n if (stableContext.signal.aborted) throw cancelledError();\n // Header providers are application code, not transport I/O. Prepare the\n // headers outside the fetch try/catch so a deterministic provider failure\n // is not accidentally retried as if it were a transient network error.\n const headers = await resolveHeaders(options, stableContext);\n let response: Response;\n try {\n if (stableContext.signal.aborted) throw cancelledError();\n const requestHeaders = new Headers(headers);\n if (stableContext.range === undefined) {\n requestHeaders.set(\"Range\", \"bytes=0-0\");\n } else {\n const end = stableContext.range.offset + stableContext.range.length - 1;\n requestHeaders.set(\"Range\", `bytes=${stableContext.range.offset}-${end}`);\n }\n response = await options.fetch(url, {\n method: \"GET\",\n headers: requestHeaders,\n ...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n signal: stableContext.signal,\n });\n } catch (error) {\n if (stableContext.signal.aborted || isAbortLike(error)) throw cancelledError();\n if (attempt + 1 >= options.maxAttempts) {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source could not be reached\", true);\n }\n await retryDelay(undefined, attempt, stableContext.signal, options);\n continue;\n }\n if (response.status === 0 && attempt + 1 < options.maxAttempts) {\n try { await response.body?.cancel(); } catch { /* best effort */ }\n await retryDelay(undefined, attempt, stableContext.signal, options);\n continue;\n }\n if (RETRYABLE_STATUSES.has(response.status) && attempt + 1 < options.maxAttempts) {\n // Release a response body before retrying. Some implementations keep a\n // connection occupied until body.cancel() is called.\n try { await response.body?.cancel(); } catch { /* best effort */ }\n await retryDelay(response, attempt, stableContext.signal, options);\n continue;\n }\n if (RETRYABLE_STATUSES.has(response.status)) {\n try { await response.body?.cancel(); } catch { /* best effort */ }\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned a temporary failure\", true, {\n status: response.status,\n });\n }\n if (response.status === 0) {\n try { await response.body?.cancel(); } catch { /* best effort */ }\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned an unavailable response\", true);\n }\n try {\n return await consume(response);\n } catch (error) {\n try { await response.body?.cancel(); } catch { /* best effort */ }\n if (!(error instanceof RetryableBodyError)) throw error;\n if (stableContext.signal.aborted) throw cancelledError();\n if (attempt + 1 >= options.maxAttempts) {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source body could not be read\", true);\n }\n await retryDelay(undefined, attempt, stableContext.signal, options);\n }\n }\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source could not be reached\", true);\n}\n\nasync function resolveHeaders(\n options: NormalizedHttpOptions,\n context: HttpHeaderContext,\n): Promise<Headers> {\n try {\n let value: HeadersInit | undefined;\n if (typeof options.headers === \"function\") {\n value = await options.headers(context);\n } else {\n value = options.headers;\n }\n if (options.getHeaders !== undefined) {\n const dynamic = await options.getHeaders(context);\n value = mergeHeaders(value, dynamic);\n }\n return new Headers(value);\n } catch (error) {\n if (context.signal.aborted) throw cancelledError();\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source request headers could not be prepared\");\n }\n}\n\nfunction mergeHeaders(first: HeadersInit | undefined, second: HeadersInit): Headers {\n const merged = new Headers(first);\n new Headers(second).forEach((value, key) => merged.set(key, value));\n return merged;\n}\n\nfunction parseContentRange(\n response: Response,\n expectedOffset: number,\n expectedLength: number,\n): { readonly total: number } | undefined {\n const value = responseHeader(response, \"Content-Range\");\n if (value === undefined) return undefined;\n const match = /^bytes ([0-9]+)-([0-9]+)\\/([0-9]+)$/u.exec(value.trim());\n if (!match) return undefined;\n const start = Number(match[1]);\n const end = Number(match[2]);\n const total = Number(match[3]);\n if (!isSafeNonNegativeInteger(start)\n || !isSafeNonNegativeInteger(end)\n || !isSafeNonNegativeInteger(total)\n || start !== expectedOffset\n || end < start\n || end - start + 1 !== expectedLength\n || end >= total) {\n return undefined;\n }\n return { total };\n}\n\nfunction parseContentLength(response: Response): number | undefined {\n const value = responseHeader(response, \"Content-Length\");\n if (value === undefined || !/^[0-9]+$/u.test(value.trim())) return undefined;\n const length = Number(value.trim());\n return isSafeNonNegativeInteger(length)\n ? length\n : undefined;\n}\n\nfunction parseUnsatisfiedContentRange(response: Response): number | undefined {\n const value = responseHeader(response, \"Content-Range\");\n if (value === undefined) return undefined;\n const match = /^bytes \\*\\/([0-9]+)$/u.exec(value.trim());\n if (!match) return undefined;\n const total = Number(match[1]);\n return isSafeNonNegativeInteger(total) ? total : undefined;\n}\n\nfunction selectValidator(\n response: Response,\n size: number,\n strength: HttpValidationStrength,\n): Validator {\n const etag = responseHeader(response, \"ETag\")?.trim();\n const validEtag = etag !== undefined\n && etag.length <= MAX_VALIDATOR_LENGTH\n && /^(?:W\\/)?\"[\\x21\\x23-\\x7e\\x80-\\xff]*\"$/u.test(etag)\n && (strength === \"weak\" || strength === \"last-modified\" || !etag.startsWith(\"W/\"));\n if (strength === \"etag\" && !validEtag) {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source has no usable ETag validator\");\n }\n if (validEtag) {\n if (strength === \"last-modified\") {\n // Continue to the explicit Last-Modified branch below.\n } else {\n return Object.freeze({\n kind: \"etag\",\n value: etag,\n strength: etag.startsWith(\"W/\") ? \"weak\" : \"strong\",\n });\n }\n }\n const lastModified = responseHeader(response, \"Last-Modified\")?.trim();\n if (lastModified !== undefined\n && lastModified.length > 0\n && lastModified.length <= MAX_VALIDATOR_LENGTH\n && isHttpDate(lastModified)) {\n return Object.freeze({\n kind: \"last-modified\",\n value: `${lastModified}|${size}`,\n strength: \"weak\",\n });\n }\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source has no usable validator\");\n}\n\nfunction isHttpDate(value: string): boolean {\n // RFC 9110 HTTP-date: preferred IMF-fixdate plus the two obsolete forms\n // recipients are required to tolerate. Date.parse alone is far too broad\n // (for example, it accepts \"0\"), so syntax is constrained first.\n const day = \"(?:0[1-9]|[12][0-9]|3[01])\";\n const month = \"(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\";\n const time = \"(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\";\n const weekday = \"(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\";\n const longWeekday = \"(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)\";\n const imf = new RegExp(`^${weekday}, ${day} ${month} [0-9]{4} ${time} GMT$`, \"u\");\n const rfc850 = new RegExp(`^${longWeekday}, ${day}-${month}-[0-9]{2} ${time} GMT$`, \"u\");\n const asctime = new RegExp(\n `^${weekday} ${month} (?: [1-9]|[12][0-9]|3[01]) ${time} [0-9]{4}$`,\n \"u\",\n );\n return (imf.test(value) || rfc850.test(value) || asctime.test(value))\n && Number.isFinite(Date.parse(value));\n}\n\nfunction validateValidator(response: Response, validator: Validator, size: number): void {\n if (validator.kind === \"etag\") {\n const current = responseHeader(response, \"ETag\")?.trim();\n if (current === undefined || current !== validator.value) {\n throw sourceError(\"SOURCE_CHANGED\", \"The source changed while it was open\");\n }\n return;\n }\n const current = responseHeader(response, \"Last-Modified\")?.trim();\n if (current === undefined || `${current}|${size}` !== validator.value) {\n throw sourceError(\"SOURCE_CHANGED\", \"The source changed while it was open\");\n }\n}\n\nfunction createSnapshot(validator: Validator, size: number): RangeSourceSnapshot {\n // Do not expose an ETag/URL in the public snapshot. This compact hash is\n // stable for the reader and opaque to diagnostics/performance telemetry.\n const id = `http-${hashOpaque(`${validator.kind}\\u0000${validator.value}\\u0000${size}`)}`;\n return Object.freeze({ id, strength: validator.strength });\n}\n\nfunction hashOpaque(value: string): string {\n // FNV-1a over UTF-16 code units; no crypto dependency is needed in workers\n // or test runtimes, and the value is only an identity hint rather than a\n // security primitive.\n let hash = 0xcbf29ce484222325n;\n for (let index = 0; index < value.length; index += 1) {\n hash ^= BigInt(value.charCodeAt(index));\n hash = BigInt.asUintN(64, hash * 0x100000001b3n);\n }\n return hash.toString(16).padStart(16, \"0\");\n}\n\n/** Accounts probe bytes that are read before a reader has joined the broker. */\nasync function readOpenResponseBody(\n response: Response,\n expectedLength: number,\n signal: AbortSignal,\n reservations: RangeSourceHostReservations | undefined,\n): Promise<ArrayBuffer> {\n const release = await reservations?.reserveStaging(expectedLength, signal);\n try {\n return await readResponseBody(response, expectedLength, signal);\n } finally {\n release?.();\n }\n}\n\n/** Marks only transport failures that are safe to replay as a fresh GET. */\nclass RetryableBodyError extends Error {\n constructor(cause: unknown) {\n super(\"The source response body transport failed\", { cause });\n this.name = \"RetryableBodyError\";\n }\n}\n\nasync function readResponseBody(\n response: Response,\n expectedLength: number,\n signal: AbortSignal,\n): Promise<ArrayBuffer> {\n if (signal.aborted) throw cancelledError();\n const rawContentLength = responseHeader(response, \"Content-Length\");\n if (rawContentLength !== undefined && parseContentLength(response) === undefined) {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned an invalid byte length\");\n }\n const contentLength = parseContentLength(response);\n if (contentLength !== undefined && contentLength !== expectedLength) {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned an unexpected byte length\", false, {\n expectedBytes: expectedLength,\n actualBytes: contentLength,\n });\n }\n const body = response.body;\n if (body !== null && body !== undefined && typeof body.getReader === \"function\") {\n const reader = body.getReader();\n const output = new Uint8Array(expectedLength);\n let offset = 0;\n const onAbort = (): void => {\n // Fetch implementations normally propagate the signal to the stream,\n // but a custom fetch/body double may not. Explicit cancellation keeps a\n // pending read from retaining a response after the caller closes or\n // aborts the reader.\n void Promise.resolve(reader.cancel()).catch(() => { /* best effort */ });\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n try {\n while (offset < expectedLength) {\n if (signal.aborted) throw cancelledError();\n const result = await readResponseChunk(reader, signal);\n if (result.done) break;\n const chunk = toUint8Array(result.value);\n if (offset + chunk.byteLength > expectedLength) {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned too many bytes\", false, {\n expectedBytes: expectedLength,\n actualBytes: offset + chunk.byteLength,\n });\n }\n output.set(chunk, offset);\n offset += chunk.byteLength;\n }\n if (offset !== expectedLength) {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned too few bytes\", false, {\n expectedBytes: expectedLength,\n actualBytes: offset,\n });\n }\n // Detect a long body even when the first expectedLength bytes arrived in\n // one chunk. A single extra read is bounded and never retained.\n const extra = await readResponseChunk(reader, signal);\n if (!extra.done) {\n const extraLength = toUint8Array(extra.value).byteLength;\n try { await reader.cancel(); } catch { /* best effort */ }\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned too many bytes\", false, {\n expectedBytes: expectedLength,\n actualBytes: expectedLength + extraLength,\n });\n }\n return output.buffer;\n } catch (error) {\n try { await reader.cancel(); } catch { /* best effort */ }\n if (signal.aborted || isAbortLike(error)) throw cancelledError();\n throw error;\n } finally {\n signal.removeEventListener(\"abort\", onAbort);\n try { reader.releaseLock(); } catch { /* best effort */ }\n }\n }\n\n if (typeof response.arrayBuffer !== \"function\") {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned no readable body\");\n }\n let rawValue: ArrayBuffer;\n try {\n rawValue = await response.arrayBuffer();\n } catch (error) {\n if (signal.aborted || isAbortLike(error)) throw cancelledError();\n throw new RetryableBodyError(error);\n }\n if (signal.aborted) throw cancelledError();\n let value: ArrayBuffer;\n try {\n value = copyRangeBytes(rawValue);\n } catch {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned an invalid body\");\n }\n if (value.byteLength !== expectedLength) {\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned an unexpected byte length\", false, {\n expectedBytes: expectedLength,\n actualBytes: value.byteLength,\n });\n }\n return value;\n}\n\nasync function readResponseChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n signal: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n try {\n return await reader.read();\n } catch (error) {\n if (signal.aborted || isAbortLike(error)) throw cancelledError();\n throw new RetryableBodyError(error);\n }\n}\n\nfunction toUint8Array(value: unknown): Uint8Array {\n if (value instanceof Uint8Array) return value;\n if (value instanceof ArrayBuffer) return new Uint8Array(value);\n if (ArrayBuffer.isView(value)) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n }\n throw sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned an invalid body\");\n}\n\nfunction responseHeader(response: Response, name: string): string | undefined {\n const headers = response.headers;\n if (headers !== undefined && headers !== null && typeof headers.get === \"function\") {\n const value = headers.get(name);\n return value === null ? undefined : value;\n }\n // A tiny compatibility path for fetch test doubles that expose a plain\n // object instead of a Headers instance.\n const raw = headers as unknown as Record<string, unknown> | undefined;\n if (raw === undefined || raw === null) return undefined;\n for (const key of Object.keys(raw)) {\n if (key.toLowerCase() === name.toLowerCase() && typeof raw[key] === \"string\") {\n return raw[key] as string;\n }\n }\n return undefined;\n}\n\nfunction responseError(status: number): TabularkError {\n return sourceError(\"SOURCE_UNAVAILABLE\", \"The source returned an unavailable response\", false, {\n ...(Number.isSafeInteger(status) && status >= 0 ? { status } : {}),\n });\n}\n\nfunction sourceError(\n code: \"SOURCE_UNAVAILABLE\" | \"SOURCE_CHANGED\" | \"RANGE_UNSUPPORTED\",\n message: string,\n retryable = false,\n details?: Readonly<Record<string, unknown>>,\n): TabularkError {\n return new TabularkError(code, message, {\n retryable,\n ...(details === undefined ? {} : { details }),\n });\n}\n\nfunction resourceLimitError(requiredBytes: number, availableBytes: number, resource: string): TabularkError {\n return new TabularkError(\"RESOURCE_LIMIT\", \"The source exceeds its configured limit\", {\n details: { resource, requiredBytes, availableBytes },\n });\n}\n\nfunction normalizeHttpError(error: unknown, fallbackMessage: string): TabularkError {\n const structured = tabularkErrorLike(error);\n if (structured !== undefined) {\n if (\n structured.code === \"SOURCE_UNAVAILABLE\"\n || structured.code === \"SOURCE_CHANGED\"\n || structured.code === \"RANGE_UNSUPPORTED\"\n || structured.code === \"RESOURCE_LIMIT\"\n || structured.code === \"CANCELLED\"\n || structured.code === \"HANDLE_CLOSED\"\n ) {\n // Rebuild the public error from a constrained vocabulary. A custom\n // fetch/provider (or a separately bundled stable entrypoint) is not\n // allowed to smuggle a URL, header, validator, message, or cause through\n // a thrown TabularkError-like value.\n if (structured.code === \"RESOURCE_LIMIT\") {\n return new TabularkError(\"RESOURCE_LIMIT\", \"The source exceeds its configured limit\", {\n details: isSafeLimitDetails(structured.details),\n });\n }\n if (structured.code === \"CANCELLED\") return cancelledError();\n if (structured.code === \"HANDLE_CLOSED\") return closedError(\"Range source reader\");\n return sourceError(\n structured.code as \"SOURCE_UNAVAILABLE\" | \"SOURCE_CHANGED\" | \"RANGE_UNSUPPORTED\",\n sourceErrorMessage(structured.code),\n structured.retryable,\n safeSourceDetails(structured.details),\n );\n }\n return sourceError(\"SOURCE_UNAVAILABLE\", fallbackMessage, true);\n }\n // AbortError names vary across browsers and fetch implementations. Never\n // retain the implementation's message because it can contain a URL.\n if (isAbortLike(error)) return cancelledError();\n return sourceError(\"SOURCE_UNAVAILABLE\", fallbackMessage, true);\n}\n\n/**\n * Stable entrypoints are independently bundled, so their TabularkError\n * constructors do not share identity. Recognize only the minimal public shape\n * and let normalizeHttpError rebuild every returned field from safe values.\n */\nfunction tabularkErrorLike(value: unknown): {\n readonly code: string;\n readonly retryable: boolean;\n readonly details: unknown;\n} | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n try {\n const candidate = value as {\n readonly code?: unknown;\n readonly retryable?: unknown;\n readonly details?: unknown;\n };\n if (typeof candidate.code !== \"string\" || typeof candidate.retryable !== \"boolean\") {\n return undefined;\n }\n return {\n code: candidate.code,\n retryable: candidate.retryable,\n details: candidate.details,\n };\n } catch {\n return undefined;\n }\n}\n\nfunction isSafeLimitDetails(value: unknown): Readonly<Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { resource: \"source-staging\", requiredBytes: 0, availableBytes: 0 };\n }\n const raw = value as Record<string, unknown>;\n const resource = typeof raw.resource === \"string\" && /^[A-Za-z0-9_.:-]{1,64}$/u.test(raw.resource)\n ? raw.resource\n : \"source-staging\";\n const requiredBytes = isSafeNonNegativeInteger(raw.requiredBytes) ? raw.requiredBytes : 0;\n const availableBytes = isSafeNonNegativeInteger(raw.availableBytes) ? raw.availableBytes : 0;\n return { resource, requiredBytes, availableBytes };\n}\n\nfunction safeSourceDetails(value: unknown): Readonly<Record<string, unknown>> | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n const raw = value as Record<string, unknown>;\n const details: Record<string, number> = {};\n for (const key of [\"status\", \"expectedBytes\", \"actualBytes\"] as const) {\n if (isSafeNonNegativeInteger(raw[key])) details[key] = raw[key];\n }\n return Object.keys(details).length === 0 ? undefined : details;\n}\n\nfunction sourceErrorMessage(code: unknown): string {\n switch (code) {\n case \"SOURCE_CHANGED\": return \"The source changed while it was open\";\n case \"RANGE_UNSUPPORTED\": return \"The source does not support the requested range\";\n default: return \"The source is unavailable\";\n }\n}\n\nfunction isAbortLike(error: unknown): boolean {\n return typeof error === \"object\"\n && error !== null\n && ((error as { name?: unknown }).name === \"AbortError\"\n || (error as { code?: unknown }).code === 20);\n}\n\nasync function retryDelay(\n response: Response | undefined,\n attempt: number,\n signal: AbortSignal,\n options: Pick<NormalizedHttpOptions, \"retryBaseDelayMs\" | \"retryMaxDelayMs\">,\n): Promise<void> {\n const retryAfter = response === undefined ? undefined : parseRetryAfter(response);\n const base = retryAfter ?? Math.min(\n options.retryMaxDelayMs,\n options.retryBaseDelayMs * 2 ** attempt,\n );\n const jittered = retryAfter === undefined\n ? Math.max(0, Math.min(options.retryMaxDelayMs, Math.round(base * (0.5 + Math.random()))))\n : Math.min(MAX_RETRY_AFTER_MS, base);\n if (jittered <= 0) return;\n await new Promise<void>((resolve, reject) => {\n if (signal.aborted) {\n reject(cancelledError());\n return;\n }\n const timer = setTimeout(done, jittered);\n const onAbort = (): void => {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", onAbort);\n reject(cancelledError());\n };\n function done(): void {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction parseRetryAfter(response: Response): number | undefined {\n const value = responseHeader(response, \"Retry-After\")?.trim();\n if (value === undefined || value.length === 0) return undefined;\n if (/^[0-9]+$/u.test(value)) {\n return Math.min(MAX_RETRY_AFTER_MS, Number(value) * 1_000);\n }\n const timestamp = Date.parse(value);\n if (!Number.isFinite(timestamp)) return undefined;\n return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, timestamp - Date.now()));\n}\n\nfunction isAbortSignal(value: unknown): value is AbortSignal {\n return typeof value === \"object\"\n && value !== null\n && typeof (value as { aborted?: unknown }).aborted === \"boolean\"\n && typeof (value as { addEventListener?: unknown }).addEventListener === \"function\";\n}\n\ninterface LinkedController {\n readonly controller: AbortController;\n readonly dispose: () => void;\n}\n\nfunction linkAbortSignal(signal: AbortSignal): LinkedController {\n const controller = new AbortController();\n const onAbort = (): void => controller.abort();\n if (signal.aborted) controller.abort();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n return {\n controller,\n dispose: () => signal.removeEventListener(\"abort\", onAbort),\n };\n}\n\nfunction combineSignals(first: AbortSignal, second: AbortSignal): AbortSignal {\n if (first === second) return first;\n const any = (AbortSignal as typeof AbortSignal & {\n any?: (signals: readonly AbortSignal[]) => AbortSignal;\n }).any;\n if (typeof any === \"function\") return any([first, second]);\n const controller = new AbortController();\n const abort = (): void => controller.abort();\n if (first.aborted || second.aborted) controller.abort();\n else {\n first.addEventListener(\"abort\", abort, { once: true });\n second.addEventListener(\"abort\", abort, { once: true });\n }\n return controller.signal;\n}\n\nclass ReadLimiter {\n #active = 0;\n #closed = false;\n readonly #limit: number;\n readonly #queue: Array<QueuedPermit> = [];\n\n constructor(limit: number) {\n this.#limit = limit;\n }\n\n acquire(signal: AbortSignal): Promise<() => void> {\n if (this.#closed) return Promise.reject(closedError(\"Range source reader\"));\n if (signal.aborted) return Promise.reject(cancelledError());\n if (this.#active < this.#limit) {\n this.#active += 1;\n return Promise.resolve(() => this.release());\n }\n return new Promise<() => void>((resolve, reject) => {\n const entry: QueuedPermit = { resolve, reject, signal, onAbort: () => undefined };\n const onAbort = (): void => {\n const index = this.#queue.indexOf(entry);\n if (index >= 0) this.#queue.splice(index, 1);\n signal.removeEventListener(\"abort\", onAbort);\n reject(cancelledError());\n };\n entry.onAbort = onAbort;\n signal.addEventListener(\"abort\", onAbort, { once: true });\n this.#queue.push(entry);\n });\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n for (const entry of this.#queue.splice(0)) {\n entry.signal.removeEventListener(\"abort\", entry.onAbort);\n entry.reject(closedError(\"Range source reader\"));\n }\n }\n\n private release(): void {\n this.#active = Math.max(0, this.#active - 1);\n if (this.#closed) return;\n const next = this.#queue.shift();\n if (next === undefined) return;\n next.signal.removeEventListener(\"abort\", next.onAbort);\n if (next.signal.aborted) {\n next.reject(cancelledError());\n this.release();\n return;\n }\n this.#active += 1;\n next.resolve(() => this.release());\n }\n}\n\ninterface QueuedPermit {\n readonly resolve: (release: () => void) => void;\n readonly reject: (error: unknown) => void;\n readonly signal: AbortSignal;\n onAbort: () => void;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["current"]
|
|
7
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Stable 0.1 browser entrypoint. */
|
|
2
|
+
export { createEngine } from "./client.js";
|
|
3
|
+
export { delimitedAdapter } from "./adapters.js";
|
|
4
|
+
export type { DatasetCapabilities, DatasetEvent, DatasetSession, EngineOptions, OpenSourceOptions, PerformanceSample, ReadRangeOptions, RuntimeProgress, SourceMode, SourceWarning, TabularkDiagnostic, TableEvent, TableHandle, TabularkEngine, Unsubscribe, } from "./client.js";
|
|
5
|
+
export type { AdapterDescriptor, DelimitedAdapterOptions, DelimitedDialect, HeaderMode, OfficialAdapterId, ParseMode, } from "./adapters.js";
|
|
6
|
+
export { TabularkError } from "./errors.js";
|
|
7
|
+
export type { TabularkErrorCode } from "./errors.js";
|
|
8
|
+
export type { ByteRange, RangeSource, RangeSourceReader, RangeSourceSnapshot, } from "./range-source.js";
|
|
9
|
+
export type { ArrowDataType, ArrowField, AxisExtent, ColumnSchema, DecimalValue, IntervalValue, MapEntryValue, MergedCellRegion, NativeListValue, NativeMapValue, NativeStructValue, NativeValue, PresentationAxisEntry, PresentationBorderSide, PresentationColor, PresentationFont, PresentationRange, PresentationStyle, RangeRequest, ReturnedRange, SpreadsheetPresentation, SpreadsheetPresentationRange, TableBatch, TableBatchColumn, TableCapabilities, TableDescriptor, TableExtent, TableMetadata, TablePresentation, TemporalValue, TimeUnit, ToRowsOptions, UnionValue, WorksheetVisibility, } from "./model.js";
|
|
10
|
+
export { createCanvasTableView } from "./view/canvas-table-view-public.js";
|
|
11
|
+
export type { CanvasTableView, CanvasTableViewControllerOptions, CanvasTableViewOptions, CanvasTableViewTheme, } from "./view/canvas-table-view-public.js";
|