pict 1.0.391 → 1.0.393
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/pict.js +80 -18
- package/dist/pict.js.map +1 -1
- package/dist/pict.min.js +2 -2
- package/dist/pict.min.js.map +1 -1
- package/package.json +3 -3
- package/source/Pict-Meadow-EntityProvider.js +49 -15
- package/types/source/Pict-Meadow-EntityProvider.d.ts +13 -2
- package/types/source/Pict-Meadow-EntityProvider.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -186,4 +186,4 @@ MIT
|
|
|
186
186
|
|
|
187
187
|
## Contributing
|
|
188
188
|
|
|
189
|
-
Pull requests are welcome. For details on our code of conduct, contribution process, and testing requirements, see the [Retold Contributing Guide](https://github.com/
|
|
189
|
+
Pull requests are welcome. For details on our code of conduct, contribution process, and testing requirements, see the [Retold Contributing Guide](https://github.com/fable-retold/retold/blob/main/docs/contributing.md).
|
package/dist/pict.js
CHANGED
|
@@ -771,7 +771,7 @@ generateUUIDv4(){let tmpBuffer=new Array(16);var tmpRandomBytes=this.randomByteG
|
|
|
771
771
|
tmpRandomBytes[6]=tmpRandomBytes[6]&0x0f|0x40;tmpRandomBytes[8]=tmpRandomBytes[8]&0x3f|0x80;return this.bytesToUUID(tmpRandomBytes);}// Simple random UUID generation
|
|
772
772
|
generateRandom(){let tmpUUID='';for(let i=0;i<this._UUIDLength;i++){tmpUUID+=this._UUIDRandomDictionary.charAt(Math.floor(Math.random()*(this._UUIDRandomDictionary.length-1)));}return tmpUUID;}// Adapted from node-uuid (https://github.com/kelektiv/node-uuid)
|
|
773
773
|
getUUID(){if(this._UUIDModeRandom){return this.generateRandom();}else{return this.generateUUIDv4();}}}// This is for backwards compatibility
|
|
774
|
-
function autoConstruct(pSettings){return new FableUUID(pSettings);}module.exports=FableUUID;module.exports.new=autoConstruct;},{"../package.json":64,"./Fable-UUID-Random.js":65,"fable-serviceproviderbase":59}],67:[function(require,module,exports){module.exports={"name":"fable","version":"3.1.
|
|
774
|
+
function autoConstruct(pSettings){return new FableUUID(pSettings);}module.exports=FableUUID;module.exports.new=autoConstruct;},{"../package.json":64,"./Fable-UUID-Random.js":65,"fable-serviceproviderbase":59}],67:[function(require,module,exports){module.exports={"name":"fable","version":"3.1.79","description":"A service dependency injection, configuration and logging library.","main":"source/Fable.js","scripts":{"start":"node source/Fable.js","coverage":"npx quack coverage","test":"npx quack test","build":"npx quack build","prepublishOnly":"npx quack build","docker-dev-build":"docker build ./ -f Dockerfile_LUXURYCode -t fable-image:local","docker-dev-run":"docker run -it -d --name fable-dev -p 30001:8080 -p 38086:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/fable\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" fable-image:local","docker-dev-shell":"docker exec -it fable-dev /bin/bash","tests":"npx quack test -g"},"mocha":{"diff":true,"extension":["js"],"package":"./package.json","reporter":"spec","slow":"75","timeout":"5000","ui":"tdd","watch-files":["source/**/*.js","test/**/*.js"],"watch-ignore":["lib/vendor"]},"browser":{"./source/service/Fable-Service-EnvironmentData.js":"./source/service/Fable-Service-EnvironmentData-Web.js","./source/service/Fable-Service-FilePersistence.js":"./source/service/Fable-Service-FilePersistence-Web.js"},"repository":{"type":"git","url":"https://github.com/fable-retold/fable.git"},"keywords":["entity","behavior"],"author":"Steven Velozo <steven@velozo.com> (http://velozo.com/)","license":"MIT","bugs":{"url":"https://github.com/fable-retold/fable/issues"},"homepage":"https://github.com/fable-retold/fable","devDependencies":{"pict-docuserve":"^1.4.19","quackage":"^1.3.0"},"dependencies":{"async.eachlimit":"^0.5.2","async.waterfall":"^0.5.2","big.js":"^7.0.1","cachetrax":"^1.0.6","cookie":"^1.1.1","data-arithmatic":"^1.0.7","dayjs":"^1.11.19","fable-log":"^3.0.18","fable-serviceproviderbase":"^3.0.19","fable-settings":"^3.0.16","fable-uuid":"^3.0.14","manyfest":"^1.0.49","simple-get":"^4.0.1"}};},{}],68:[function(require,module,exports){/**
|
|
775
775
|
* Fable Application Services Support Library
|
|
776
776
|
* @author <steven@velozo.com>
|
|
777
777
|
*/// Pre-init services
|
|
@@ -2801,7 +2801,18 @@ if(tmpProgressTracker.CurrentCount<1&&tmpProgressTracker.EndTimeStamp<1){return`
|
|
|
2801
2801
|
else if(tmpProgressTracker.EndTimeStamp<1){return`ProgressTracker ${tmpProgressTracker.Hash} is ${tmpProgressTracker.PercentComplete.toFixed(3)}% completed - ${tmpProgressTracker.CurrentCount} / ${tmpProgressTracker.TotalCount} operations over ${this.progressTimes.formatTimeDuration(tmpProgressTracker.ElapsedTime)} (median ${this.progressTimes.formatTimeDuration(tmpProgressTracker.AverageOperationTime)} per). Estimated completion: ${this.progressTimes.formatTimeDuration(tmpProgressTracker.EstimatedCompletionTime)}`;}// 4. Done
|
|
2802
2802
|
else{return`ProgressTracker ${tmpProgressTracker.Hash} is done. ${tmpProgressTracker.CurrentCount} / ${tmpProgressTracker.TotalCount} operations were completed in ${this.progressTimes.formatTimeDuration(tmpProgressTracker.ElapsedTime)} (median ${this.progressTimes.formatTimeDuration(tmpProgressTracker.AverageOperationTime)} per).`;}}}logProgressTrackerStatus(pProgressTrackerHash){this.fable.log.info(this.getProgressTrackerStatusString(pProgressTrackerHash));}}module.exports=FableServiceProgressTrackerSet;},{"./Fable-Service-ProgressTracker/ProgressTracker.js":96,"fable-serviceproviderbase":59}],98:[function(require,module,exports){(function(Buffer){(function(){const libFableServiceBase=require('fable-serviceproviderbase');const libSimpleGet=require('simple-get');const libCookie=require('cookie');const libHttp=require('http');const libHttps=require('https');class FableServiceRestClient extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.TraceLog=false;if(this.options.TraceLog||this.fable.TraceLog){this.TraceLog=true;}this.dataFormat=this.fable.services.DataFormat;this.serviceType='RestClient';this.cookie=false;// This is a function that can be overridden, to allow the management
|
|
2803
2803
|
// of the request options before they are passed to the request library.
|
|
2804
|
-
this.prepareRequestOptions=pOptions=>{return pOptions;};//
|
|
2804
|
+
this.prepareRequestOptions=pOptions=>{return pOptions;};// Optional, UI-agnostic authentication-recovery hook. Default null, so
|
|
2805
|
+
// existing server-to-server callers are completely unaffected. When set
|
|
2806
|
+
// to an (async) function and a completed response has statusCode 401 on a
|
|
2807
|
+
// request that is not itself a replay, the client awaits this hook; a
|
|
2808
|
+
// truthy resolution replays the original request exactly once, anything
|
|
2809
|
+
// else returns the original 401 to the caller unchanged. The hook never
|
|
2810
|
+
// imports app UI -- the app assigns it (e.g. a re-auth modal controller),
|
|
2811
|
+
// which is what makes recovery reusable across every Fable consumer.
|
|
2812
|
+
this.authenticationRecovery=null;// Single-flight state for the recovery hook: a burst of concurrent 401s
|
|
2813
|
+
// collapses to exactly one authenticationRecovery() call. Cleared on
|
|
2814
|
+
// settle so a later, unrelated expiry re-arms recovery.
|
|
2815
|
+
this._authenticationRecoveryPromise=null;// Default per-request timeout (ms). Applied in preRequest when a caller
|
|
2805
2816
|
// does not supply their own. Node 20+ installs a ~5s socket timeout on
|
|
2806
2817
|
// http.globalAgent that aborts legitimately long-running requests; any
|
|
2807
2818
|
// explicit `timeout` on the request options takes that default out of
|
|
@@ -2907,15 +2918,54 @@ pResponse.resume();let tmpRedirectsRemaining=typeof pOptions.maxRedirects==='num
|
|
|
2907
2918
|
// (possibly different) protocol of the redirect target. We do
|
|
2908
2919
|
// NOT re-run preRequest in full — RestClientURLPrefix and
|
|
2909
2920
|
// prepareCookies are first-call-only.
|
|
2910
|
-
const tmpPreparedNext=this.prepareRequestOptions(tmpNextOptions);if(this.TraceLog){this.fable.log.debug(`--> redirect ${pResponse.statusCode} to ${tmpPreparedNext.url}`);}return this._executeWithRedirects(tmpPreparedNext,fCallback);});}executeChunkedRequest(pOptions,fCallback){let tmpOptions=this.preRequest(pOptions);tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} request to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}return this._executeWithRedirects(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpData='';pResponse.on('data',pChunk=>{// For JSON, the chunk is the serialized object.
|
|
2911
|
-
if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> ${tmpOptions.method} data chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}tmpData+=pChunk;});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> ${tmpOptions.method} completed data size ${tmpData.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}return
|
|
2921
|
+
const tmpPreparedNext=this.prepareRequestOptions(tmpNextOptions);if(this.TraceLog){this.fable.log.debug(`--> redirect ${pResponse.statusCode} to ${tmpPreparedNext.url}`);}return this._executeWithRedirects(tmpPreparedNext,fCallback);});}executeChunkedRequest(pOptions,fCallback){let tmpReplayOptions=this._captureReplayOptions(pOptions);let tmpOptions=this.preRequest(pOptions);tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} request to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}return this._executeWithRedirects(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpData='';pResponse.on('data',pChunk=>{// For JSON, the chunk is the serialized object.
|
|
2922
|
+
if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> ${tmpOptions.method} data chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}tmpData+=pChunk;});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> ${tmpOptions.method} completed data size ${tmpData.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}return this._completeWithRecovery(tmpReplayOptions,pError,pResponse,tmpData,()=>this.executeChunkedRequest(tmpReplayOptions,fCallback),fCallback);});});}executeChunkedRequestBinary(pOptions,fCallback){let tmpReplayOptions=this._captureReplayOptions(pOptions);let tmpOptions=this.preRequest(pOptions);tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} request to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}tmpOptions.json=false;tmpOptions.encoding=null;return this._executeWithRedirects(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpDataBuffer=false;pResponse.on('data',pChunk=>{// For JSON, the chunk is the serialized object.
|
|
2912
2923
|
if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> ${tmpOptions.method} data chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}// TODO: Potentially create a third option that streams this to a file? So it doesn't have to hold it all in memory.
|
|
2913
|
-
if(!tmpDataBuffer){tmpDataBuffer=Buffer.from(pChunk);}else{tmpDataBuffer=Buffer.concat([tmpDataBuffer,pChunk]);}});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> ${tmpOptions.method} completed data size ${tmpDataBuffer.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}return
|
|
2924
|
+
if(!tmpDataBuffer){tmpDataBuffer=Buffer.from(pChunk);}else{tmpDataBuffer=Buffer.concat([tmpDataBuffer,pChunk]);}});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> ${tmpOptions.method} completed data size ${tmpDataBuffer.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}return this._completeWithRecovery(tmpReplayOptions,pError,pResponse,tmpDataBuffer,()=>this.executeChunkedRequestBinary(tmpReplayOptions,fCallback),fCallback);});});}/**
|
|
2925
|
+
* Shallow-snapshot the caller's options BEFORE preRequest mutates them, so a
|
|
2926
|
+
* recovery replay can re-run the same request cleanly. preRequest prepends
|
|
2927
|
+
* RestClientURLPrefix to `url` in place; replaying the already-mutated object
|
|
2928
|
+
* would double-prefix. Replaying from this snapshot re-runs preRequest once.
|
|
2929
|
+
*
|
|
2930
|
+
* @param {Object} pOptions - The caller's request options.
|
|
2931
|
+
* @return {Object} A shallow copy safe to re-issue.
|
|
2932
|
+
* @private
|
|
2933
|
+
*/_captureReplayOptions(pOptions){return Object.assign({},pOptions);}/**
|
|
2934
|
+
* Invoke the authenticationRecovery hook under a single-flight guard. A burst
|
|
2935
|
+
* of concurrent 401s shares one hook invocation; all await the same promise,
|
|
2936
|
+
* then each replays independently. The shared promise is cleared on settle so
|
|
2937
|
+
* a later, unrelated expiry re-arms recovery. Resolves to a strict boolean
|
|
2938
|
+
* (true only when the hook resolved exactly true); rejects if the hook throws.
|
|
2939
|
+
*
|
|
2940
|
+
* @param {Object} pRequestContext - Context passed to the hook ({ options, response }).
|
|
2941
|
+
* @return {Promise<boolean>}
|
|
2942
|
+
* @private
|
|
2943
|
+
*/_runAuthenticationRecovery(pRequestContext){if(this._authenticationRecoveryPromise){return this._authenticationRecoveryPromise;}let tmpInvocation;try{tmpInvocation=Promise.resolve(this.authenticationRecovery(pRequestContext));}catch(pError){tmpInvocation=Promise.reject(pError);}this._authenticationRecoveryPromise=tmpInvocation.then(pResult=>{this._authenticationRecoveryPromise=null;return pResult===true;},pError=>{this._authenticationRecoveryPromise=null;throw pError;});return this._authenticationRecoveryPromise;}/**
|
|
2944
|
+
* Shared completion seam for every request path. On a completed 401, with a
|
|
2945
|
+
* recovery hook installed, on a request that is not itself already a replay,
|
|
2946
|
+
* it awaits recovery: on success it replays the request exactly once (via
|
|
2947
|
+
* fReplay, whose pReplayOptions carry the __authRetry marker so the replay can
|
|
2948
|
+
* never re-enter recovery -- a hard one-retry cap); otherwise it delivers the
|
|
2949
|
+
* original response to fCallback unchanged. Every other outcome (2xx, 5xx,
|
|
2950
|
+
* timeout, no hook) passes straight through, so opt-out callers are untouched.
|
|
2951
|
+
*
|
|
2952
|
+
* @param {Object} pReplayOptions - The replay snapshot (also carries the retry marker).
|
|
2953
|
+
* @param {Error|null} pError - The error from the request, if any.
|
|
2954
|
+
* @param {Object} pResponse - The response object (statusCode read here).
|
|
2955
|
+
* @param {*} pBody - The processed body for this path (parsed JSON / string / Buffer).
|
|
2956
|
+
* @param {Function} fReplay - Re-issues the request from pReplayOptions.
|
|
2957
|
+
* @param {Function} fCallback - The caller's callback (pError, pResponse, pBody).
|
|
2958
|
+
* @private
|
|
2959
|
+
*/_completeWithRecovery(pReplayOptions,pError,pResponse,pBody,fReplay,fCallback){if(pResponse&&pResponse.statusCode===401&&typeof this.authenticationRecovery==='function'&&!pReplayOptions.__authRetry){// Stamp the one-retry marker before recovery so the replay can never
|
|
2960
|
+
// itself trigger another recovery pass.
|
|
2961
|
+
pReplayOptions.__authRetry=true;this._runAuthenticationRecovery({options:pReplayOptions,response:pResponse}).then(pRecovered=>{if(pRecovered===true){return fReplay();}return fCallback(pError,pResponse,pBody);},()=>{// A throwing/rejecting recovery is treated as "not recovered":
|
|
2962
|
+
// hand the original 401 back untouched.
|
|
2963
|
+
return fCallback(pError,pResponse,pBody);});return;}return fCallback(pError,pResponse,pBody);}executeJSONRequest(pOptions,fCallback){pOptions.json=true;let tmpReplayOptions=this._captureReplayOptions(pOptions);let tmpOptions=this.preRequest(pOptions);if(!('headers'in tmpOptions)){tmpOptions.headers={};}/* Automated headers break some APIs
|
|
2914
2964
|
if (!('Content-Type' in tmpOptions.headers))
|
|
2915
2965
|
{
|
|
2916
2966
|
tmpOptions.headers['Content-Type'] = 'application/json';
|
|
2917
2967
|
}
|
|
2918
|
-
*/tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} JSON request to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}return this._executeWithRedirects(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> JSON ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpJSONData='';pResponse.on('data',pChunk=>{if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> JSON ${tmpOptions.method} data chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}tmpJSONData+=pChunk;});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> JSON ${tmpOptions.method} completed - received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}let tmpParsedJSON;try{tmpParsedJSON=JSON.parse(tmpJSONData);}catch(pParseError){let tmpStatusCode=pResponse?pResponse.statusCode:'unknown';return fCallback(new Error(`JSON parse failed (HTTP ${tmpStatusCode}): ${tmpJSONData.substring(0,200)}`),pResponse,null);}return
|
|
2968
|
+
*/tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} JSON request to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}return this._executeWithRedirects(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> JSON ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpJSONData='';pResponse.on('data',pChunk=>{if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> JSON ${tmpOptions.method} data chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}tmpJSONData+=pChunk;});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> JSON ${tmpOptions.method} completed - received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}let tmpParsedJSON;try{tmpParsedJSON=JSON.parse(tmpJSONData);}catch(pParseError){let tmpStatusCode=pResponse?pResponse.statusCode:'unknown';return fCallback(new Error(`JSON parse failed (HTTP ${tmpStatusCode}): ${tmpJSONData.substring(0,200)}`),pResponse,null);}return this._completeWithRecovery(tmpReplayOptions,pError,pResponse,tmpParsedJSON,()=>this.executeJSONRequest(tmpReplayOptions,fCallback),fCallback);});});}getJSON(pOptionsOrURL,fCallback){let tmpRequestOptions=typeof pOptionsOrURL=='object'?pOptionsOrURL:{};if(typeof pOptionsOrURL=='string'){tmpRequestOptions.url=pOptionsOrURL;}tmpRequestOptions.method='GET';return this.executeJSONRequest(tmpRequestOptions,fCallback);}putJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`PUT JSON Error Invalid options object`));}pOptions.method='PUT';return this.executeJSONRequest(pOptions,fCallback);}postJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`POST JSON Error Invalid options object`));}pOptions.method='POST';return this.executeJSONRequest(pOptions,fCallback);}patchJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`PATCH JSON Error Invalid options object`));}pOptions.method='PATCH';return this.executeJSONRequest(pOptions,fCallback);}headJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`HEAD JSON Error Invalid options object`));}pOptions.method='HEAD';return this.executeJSONRequest(pOptions,fCallback);}delJSON(pOptions,fCallback){pOptions.method='DELETE';return this.executeJSONRequest(pOptions,fCallback);}/**
|
|
2919
2969
|
* Upload binary data via POST.
|
|
2920
2970
|
*
|
|
2921
2971
|
* Accepts Buffer, Blob, or File as the body. In the browser, Blob/File
|
|
@@ -2937,8 +2987,10 @@ return this._executeBinaryUploadInternal(pOptions,fCallback,fOnProgress);}/**
|
|
|
2937
2987
|
* @param {(pError?: Error, pResponse: any, pBody?: any) => void} fCallback - Callback (pError, pResponse, pBody)
|
|
2938
2988
|
* @param {(pProgress: number) => void} [fOnProgress] - Optional progress callback (0.0 to 1.0); called with 1.0 on completion
|
|
2939
2989
|
* @private
|
|
2940
|
-
*/_executeBinaryUploadInternal(pOptions,fCallback,fOnProgress){let tmpOptions=this.preRequest(pOptions);tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} binary upload to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}tmpOptions.json=false;return this._executeWithRedirects(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> Binary upload ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpData='';pResponse.on('data',pChunk=>{if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> Binary upload ${tmpOptions.method} response chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}tmpData+=pChunk;});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> Binary upload ${tmpOptions.method} completed in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}//
|
|
2941
|
-
|
|
2990
|
+
*/_executeBinaryUploadInternal(pOptions,fCallback,fOnProgress){let tmpReplayOptions=this._captureReplayOptions(pOptions);let tmpOptions=this.preRequest(pOptions);tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} binary upload to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}tmpOptions.json=false;return this._executeWithRedirects(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> Binary upload ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpData='';pResponse.on('data',pChunk=>{if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> Binary upload ${tmpOptions.method} response chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}tmpData+=pChunk;});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> Binary upload ${tmpOptions.method} completed in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}// Deliver terminally: fire the completion progress only when
|
|
2991
|
+
// we actually hand the response back (not when we are about to
|
|
2992
|
+
// replay after recovery -- the replay signals its own progress).
|
|
2993
|
+
let fDeliver=(pDeliverError,pDeliverResponse,pDeliverBody)=>{if(typeof fOnProgress==='function'){fOnProgress(1.0);}return fCallback(pDeliverError,pDeliverResponse,pDeliverBody);};return this._completeWithRecovery(tmpReplayOptions,pError,pResponse,tmpData,()=>this._executeBinaryUploadInternal(tmpReplayOptions,fCallback,fOnProgress),fDeliver);});});}getRawText(pOptionsOrURL,fCallback){let tmpRequestOptions=typeof pOptionsOrURL=='object'?pOptionsOrURL:{};if(typeof pOptionsOrURL=='string'){tmpRequestOptions.url=pOptionsOrURL;}tmpRequestOptions.method='GET';return this.executeChunkedRequest(tmpRequestOptions,fCallback);}}module.exports=FableServiceRestClient;}).call(this);}).call(this,require("buffer").Buffer);},{"buffer":20,"cookie":31,"fable-serviceproviderbase":59,"http":167,"https":113,"simple-get":166}],99:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');class FableServiceTemplate extends libFableServiceBase{// Underscore and lodash have a behavior, _.template, which compiles a
|
|
2942
2994
|
// string-based template with code snippets into simple executable pieces,
|
|
2943
2995
|
// with the added twist of returning a precompiled function ready to go.
|
|
2944
2996
|
//
|
|
@@ -6218,7 +6270,7 @@ try{if(!global.localStorage)return false;}catch(_){return false;}var val=global.
|
|
|
6218
6270
|
// presumably different callback function.
|
|
6219
6271
|
// This makes sure that own properties are retained, so that
|
|
6220
6272
|
// decorations and such are not lost along the way.
|
|
6221
|
-
module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(typeof fn!=='function')throw new TypeError('need wrapper function');Object.keys(fn).forEach(function(k){wrapper[k]=fn[k];});return wrapper;function wrapper(){var args=new Array(arguments.length);for(var i=0;i<args.length;i++){args[i]=arguments[i];}var ret=fn.apply(this,args);var cb=args[args.length-1];if(typeof ret==='function'&&ret!==cb){Object.keys(cb).forEach(function(k){ret[k]=cb[k];});}return ret;}}},{}],191:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],192:[function(require,module,exports){module.exports={"name":"pict","version":"1.0.
|
|
6273
|
+
module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(typeof fn!=='function')throw new TypeError('need wrapper function');Object.keys(fn).forEach(function(k){wrapper[k]=fn[k];});return wrapper;function wrapper(){var args=new Array(arguments.length);for(var i=0;i<args.length;i++){args[i]=arguments[i];}var ret=fn.apply(this,args);var cb=args[args.length-1];if(typeof ret==='function'&&ret!==cb){Object.keys(cb).forEach(function(k){ret[k]=cb[k];});}return ret;}}},{}],191:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],192:[function(require,module,exports){module.exports={"name":"pict","version":"1.0.393","description":"Pict browser library.","main":"source/Pict.js","scripts":{"start":"node source/Pict.js","test":"npx quack test","tests":"npx quack test -g","coverage":"npx quack coverage","build":"npx quack build","prepublishOnly":"npx quack build","docker-dev-build":"docker build ./ -f Dockerfile_LUXURYCode -t pict-image:local","docker-dev-run":"docker run -it -d --name pict-dev -p 37447:8080 -p 19506:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/pict\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" pict-image:local","docker-dev-shell":"docker exec -it pict-dev /bin/bash","lint":"eslint source/**/*.js test/**/*.js","types":"tsc -p ."},"files":["source/","dist/","types/"],"types":"types/source/Pict.d.ts","mocha":{"diff":true,"extension":["js"],"package":"./package.json","reporter":"spec","slow":"75","timeout":"5000","ui":"tdd","watch-files":["source/**/*.js","test/**/*.js"],"watch-ignore":["lib/vendor"]},"repository":{"type":"git","url":"git+https://github.com/fable-retold/pict.git"},"author":"steven velozo <steven@velozo.com>","license":"MIT","bugs":{"url":"https://github.com/fable-retold/pict/issues"},"homepage":"https://github.com/fable-retold/pict#readme","devDependencies":{"@eslint/js":"^9.39.1","@types/jquery":"^3.5.33","@types/sinon":"^17.0.4","eslint":"^9.39.1","globals":"^16.5.0","pict-docuserve":"^1.4.19","quackage":"^1.3.0","sinon":"^20.0.0","typescript":"^5.9.3"},"dependencies":{"cachetrax":"^1.0.6","fable":"^3.1.79","pict-application":"^1.0.34","pict-provider":"^1.0.13","pict-template":"^1.0.15","pict-view":"^1.0.68"}};},{}],193:[function(require,module,exports){// This assumes Pict has been required in the browser. Delcare these as globals so linter can do its job.
|
|
6222
6274
|
/* global Pict, _Pict: writeable *//**
|
|
6223
6275
|
* Simple function to load a pict Application
|
|
6224
6276
|
*
|
|
@@ -6506,15 +6558,23 @@ for(let i=0;i<3;i++){const tmpHave=isNaN(tmpParts[i])?0:tmpParts[i];const tmpNee
|
|
|
6506
6558
|
* @return {void}
|
|
6507
6559
|
*/resolveEntityQuerySupport(pEntity,pURLPrefix,fCallback){if(!this.useQueryEndpoint){return fCallback(null,false);}const tmpKey=this._capabilityKey(pEntity,pURLPrefix);if(tmpKey in this.endpointCapabilityCache){return fCallback(null,this.endpointCapabilityCache[tmpKey].SupportsQuery);}if(this.endpointCapabilityInflight[tmpKey]){this.endpointCapabilityInflight[tmpKey].push(fCallback);return;}this.endpointCapabilityInflight[tmpKey]=[fCallback];/** @type {Record<string, any>} */let tmpOptions={url:`${pURLPrefix||this.options.urlPrefix}${pEntity}/Schema`};tmpOptions=this.prepareRequestOptions(tmpOptions);this.restClient.getJSON(tmpOptions,(pError,pResponse,pBody)=>{let tmpSupportsQuery=false;if(!pError){try{tmpSupportsQuery=this.evaluateQueryEndpointSupport(pBody);}catch(pEvaluateError){tmpSupportsQuery=false;}// Only cache on a clean probe; transient errors stay re-probeable.
|
|
6508
6560
|
this.endpointCapabilityCache[tmpKey]={SupportsQuery:tmpSupportsQuery,Metadata:pBody&&pBody.RetoldMetadata||null};}else{this.log.warn(`EntityProvider capability probe for [${pEntity}] failed; falling back to GET reads: ${pError}`);}const tmpCallbacks=this.endpointCapabilityInflight[tmpKey];delete this.endpointCapabilityInflight[tmpKey];for(let i=0;i<tmpCallbacks.length;i++){tmpCallbacks[i](null,tmpSupportsQuery);}});}/**
|
|
6561
|
+
* Normalize a step Projection into lite-read shaping. `Lite` and
|
|
6562
|
+
* `LiteExtended` both map to a lite read; `LiteExtended` with no
|
|
6563
|
+
* ExtraColumns degrades to a plain Lite read.
|
|
6564
|
+
*
|
|
6565
|
+
* @param {Record<string, any>} [pProjection] - Optional { Mode:'Lite'|'LiteExtended', ExtraColumns:[...] }.
|
|
6566
|
+
* @return {{ ExtraColumns: string|null }|null} Lite-read shaping, or null for a full read.
|
|
6567
|
+
*/_resolveLiteProjection(pProjection){if(!pProjection||pProjection.Mode!=='Lite'&&pProjection.Mode!=='LiteExtended'){return null;}const tmpExtraColumns=Array.isArray(pProjection.ExtraColumns)&&pProjection.ExtraColumns.length>0?pProjection.ExtraColumns.join(','):null;return{ExtraColumns:tmpExtraColumns};}/**
|
|
6509
6568
|
* Build the POST /:Entity/Query request body for a filtered read.
|
|
6510
6569
|
*
|
|
6511
6570
|
* @param {string} pMeadowFilterExpression - The meadow filter string (may be empty).
|
|
6512
6571
|
* @param {number|null} [pBegin] - Pagination start cursor.
|
|
6513
6572
|
* @param {number|null} [pCap] - Pagination page size.
|
|
6514
|
-
* @param {Record<string, any>} [pProjection] - Optional { Mode:'LiteExtended', ExtraColumns:[...] }.
|
|
6573
|
+
* @param {Record<string, any>} [pProjection] - Optional { Mode:'Lite'|'LiteExtended', ExtraColumns:[...] }.
|
|
6515
6574
|
* @return {Record<string, any>} The request body envelope.
|
|
6516
|
-
*/_buildQueryReadBody(pMeadowFilterExpression,pBegin,pCap,pProjection){/** @type {Record<string, any>} */const tmpBody={};if(pMeadowFilterExpression){tmpBody.Filter=pMeadowFilterExpression;}if(typeof pBegin==='number'){tmpBody.Begin=pBegin;}if(typeof pCap==='number'){tmpBody.Cap=pCap;}
|
|
6517
|
-
|
|
6575
|
+
*/_buildQueryReadBody(pMeadowFilterExpression,pBegin,pCap,pProjection){/** @type {Record<string, any>} */const tmpBody={};if(pMeadowFilterExpression){tmpBody.Filter=pMeadowFilterExpression;}if(typeof pBegin==='number'){tmpBody.Begin=pBegin;}if(typeof pCap==='number'){tmpBody.Cap=pCap;}const tmpLiteProjection=this._resolveLiteProjection(pProjection);if(tmpLiteProjection){// Lite/LiteExtended GET reads map to a Lite Query read; ExtraColumns
|
|
6576
|
+
// carries the LiteExtended column list when present.
|
|
6577
|
+
tmpBody.Lite=true;if(tmpLiteProjection.ExtraColumns){tmpBody.ExtraColumns=tmpLiteProjection.ExtraColumns;}}return tmpBody;}/**
|
|
6518
6578
|
* Read a page of an entity set, using POST /:Entity/Query when supported and
|
|
6519
6579
|
* falling back to the legacy GET read otherwise. The callback mirrors
|
|
6520
6580
|
* restClient.getJSON exactly: (pError, pResponse, pBody).
|
|
@@ -6526,7 +6586,7 @@ tmpBody.Lite=true;tmpBody.ExtraColumns=pProjection.ExtraColumns.join(',');}retur
|
|
|
6526
6586
|
* @param {Record<string, any>} pReadOptions - { SupportsQuery, URLPrefix, Postfix, Projection }.
|
|
6527
6587
|
* @param {(pError: Error|null, pResponse: any, pBody: any) => void} fCallback - Completion callback.
|
|
6528
6588
|
* @return {void}
|
|
6529
|
-
*/_readEntityPage(pEntity,pMeadowFilterExpression,pBegin,pCap,pReadOptions,fCallback){const tmpURLPrefix=pReadOptions&&pReadOptions.URLPrefix||this.options.urlPrefix;const tmpPostfix=pReadOptions&&pReadOptions.Postfix||'';const tmpProjection=pReadOptions?pReadOptions.Projection:null;if(pReadOptions&&pReadOptions.SupportsQuery){const tmpRequestOptions={url:`${tmpURLPrefix}${pEntity}s/Query${tmpPostfix}`,body:this._buildQueryReadBody(pMeadowFilterExpression,pBegin,pCap,tmpProjection)};return this.restClient.postJSON(tmpRequestOptions,fCallback);}const tmpFilterStanza=pMeadowFilterExpression?`/FilteredTo/${pMeadowFilterExpression}`:'';const
|
|
6589
|
+
*/_readEntityPage(pEntity,pMeadowFilterExpression,pBegin,pCap,pReadOptions,fCallback){const tmpURLPrefix=pReadOptions&&pReadOptions.URLPrefix||this.options.urlPrefix;const tmpPostfix=pReadOptions&&pReadOptions.Postfix||'';const tmpProjection=pReadOptions?pReadOptions.Projection:null;if(pReadOptions&&pReadOptions.SupportsQuery){const tmpRequestOptions={url:`${tmpURLPrefix}${pEntity}s/Query${tmpPostfix}`,body:this._buildQueryReadBody(pMeadowFilterExpression,pBegin,pCap,tmpProjection)};return this.restClient.postJSON(tmpRequestOptions,fCallback);}const tmpFilterStanza=pMeadowFilterExpression?`/FilteredTo/${pMeadowFilterExpression}`:'';const tmpLiteProjection=this._resolveLiteProjection(tmpProjection);const tmpProjectionStanza=tmpLiteProjection?tmpLiteProjection.ExtraColumns?`/LiteExtended/${tmpLiteProjection.ExtraColumns}`:'/Lite':'';const tmpPageStanza=typeof pBegin==='number'&&typeof pCap==='number'?`/${pBegin}/${pCap}`:'';const tmpURL=`${tmpURLPrefix}${pEntity}s${tmpProjectionStanza}${tmpFilterStanza}${tmpPageStanza}${tmpPostfix}`;return this.restClient.getJSON(tmpURL,fCallback);}/**
|
|
6530
6590
|
* Read the count of an entity set, using POST /:Entity/Query (Count mode)
|
|
6531
6591
|
* when supported and the legacy GET Count otherwise. The callback mirrors
|
|
6532
6592
|
* restClient.getJSON: (pError, pResponse, pBody) where pBody carries .Count.
|
|
@@ -6843,25 +6903,27 @@ else if(tmpColumnName in this.entityColumnTranslations){tmpIDColumnsToCache.push
|
|
|
6843
6903
|
* @param {string} pMeadowFilterExpression - The meadow filter expression to filter the entity set by.
|
|
6844
6904
|
* @param {(pError?: Error, pEntitySet?: Array) => void} fCallback - The callback to call when the request is complete.
|
|
6845
6905
|
* @param {string} [postfix] - Optional, adds a postfix string to all calls made.
|
|
6846
|
-
* @param {Record<string, any>} [pOptions] - Optional, per-call options (e.g. { DownloadPageConcurrency: 1 }).
|
|
6906
|
+
* @param {Record<string, any>} [pOptions] - Optional, per-call options (e.g. { DownloadPageConcurrency: 1, Projection: { Mode: 'LiteExtended', ExtraColumns: [...] } }).
|
|
6847
6907
|
*
|
|
6848
6908
|
* @return {void}
|
|
6849
|
-
*/getEntitySet(pEntity,pMeadowFilterExpression,fCallback){let postfix=arguments.length>3&&arguments[3]!==undefined?arguments[3]:'';let pOptions=arguments.length>4&&arguments[4]!==undefined?arguments[4]:{};const tmpURLPrefix=pOptions.URLPrefix||this.options.urlPrefix;const tmpScope=pOptions&&pOptions.Scope?pOptions.Scope:'';this.initializeCache(pEntity,tmpScope);const tmpCacheKey=this._cacheKey(pEntity,tmpScope);// Resolve transport capability once for the whole read (count + every
|
|
6909
|
+
*/getEntitySet(pEntity,pMeadowFilterExpression,fCallback){let postfix=arguments.length>3&&arguments[3]!==undefined?arguments[3]:'';let pOptions=arguments.length>4&&arguments[4]!==undefined?arguments[4]:{};const tmpURLPrefix=pOptions.URLPrefix||this.options.urlPrefix;const tmpScope=pOptions&&pOptions.Scope?pOptions.Scope:'';const tmpProjection=pOptions&&pOptions.Projection?pOptions.Projection:null;this.initializeCache(pEntity,tmpScope);const tmpCacheKey=this._cacheKey(pEntity,tmpScope);// Resolve transport capability once for the whole read (count + every
|
|
6850
6910
|
// page share the same SupportsQuery flag). The legacy GET reads embed the
|
|
6851
6911
|
// filter (and any large IN-list) in the URI, which is exactly the long-URI
|
|
6852
6912
|
// failure POST /:Entity/Query avoids when the server supports it.
|
|
6853
|
-
this.resolveEntityQuerySupport(pEntity,tmpURLPrefix,(pSupportError,pSupportsQuery)=>{const tmpReadOptions={SupportsQuery:pSupportsQuery,URLPrefix:tmpURLPrefix,Postfix:postfix||''};// Discard anything from the cache that has expired or is over size.
|
|
6913
|
+
this.resolveEntityQuerySupport(pEntity,tmpURLPrefix,(pSupportError,pSupportsQuery)=>{const tmpReadOptions={SupportsQuery:pSupportsQuery,URLPrefix:tmpURLPrefix,Postfix:postfix||'',Projection:tmpProjection};// Discard anything from the cache that has expired or is over size.
|
|
6854
6914
|
this.recordSetCache[tmpCacheKey].prune(function(){let tmpPossibleRecords=this.recordSetCache[tmpCacheKey].read(pMeadowFilterExpression);if(tmpPossibleRecords){return fCallback(null,tmpPossibleRecords);}if(pOptions.NoCount){// Lazily load until we hit a not full page rather than using couns.
|
|
6855
6915
|
// Does not respect parallelization.
|
|
6856
6916
|
const pageSize=250;let page=0;let returnSet=[];const recursiveCallback=(pDownloadError,pDownloadResponse,pDownloadBody)=>{// A transport-level failure (e.g. connection reset, expired TLS
|
|
6857
6917
|
// cert) calls back with no response, so guard every pDownloadResponse
|
|
6858
6918
|
// deref and surface the underlying error rather than throwing a
|
|
6859
6919
|
// TypeError on the missing statusCode.
|
|
6860
|
-
if(pDownloadError||pDownloadResponse&&pDownloadResponse.statusCode&&pDownloadResponse.statusCode>=400||!Array.isArray(pDownloadBody)){const tmpStatusCode=pDownloadResponse?pDownloadResponse.statusCode:'no response';const tmpStatusDetail=pDownloadError?pDownloadError.message||pDownloadError:pDownloadResponse?pDownloadResponse.statusMessage:'';this.log.error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${tmpStatusCode} ${tmpStatusDetail}`);return fCallback(pDownloadError||new Error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${tmpStatusCode} ${JSON.stringify(pDownloadBody||{})}`),[]);}returnSet=returnSet.concat(pDownloadBody);if((pDownloadBody===null||pDownloadBody===void 0?void 0:pDownloadBody.length)<pageSize){
|
|
6920
|
+
if(pDownloadError||pDownloadResponse&&pDownloadResponse.statusCode&&pDownloadResponse.statusCode>=400||!Array.isArray(pDownloadBody)){const tmpStatusCode=pDownloadResponse?pDownloadResponse.statusCode:'no response';const tmpStatusDetail=pDownloadError?pDownloadError.message||pDownloadError:pDownloadResponse?pDownloadResponse.statusMessage:'';this.log.error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${tmpStatusCode} ${tmpStatusDetail}`);return fCallback(pDownloadError||new Error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${tmpStatusCode} ${JSON.stringify(pDownloadBody||{})}`),[]);}returnSet=returnSet.concat(pDownloadBody);if((pDownloadBody===null||pDownloadBody===void 0?void 0:pDownloadBody.length)<pageSize){// Do not cache projected (partial) records — see getEntitySetPage.
|
|
6921
|
+
if(!tmpProjection){this.recordSetCache[tmpCacheKey].put(returnSet,pMeadowFilterExpression);this.cacheIndividualEntityRecords(pEntity,returnSet,tmpScope);}fCallback(null,returnSet);}else{page+=1;this._readEntityPage(pEntity,pMeadowFilterExpression,page*pageSize,pageSize,tmpReadOptions,recursiveCallback);}};return this._readEntityPage(pEntity,pMeadowFilterExpression,page*pageSize,pageSize,tmpReadOptions,recursiveCallback);}return this.getEntitySetRecordCount(pEntity,pMeadowFilterExpression,(pRecordCountError,pRecordCount)=>{if(pRecordCountError){return fCallback(pRecordCountError);}let tmpRecordCount=pRecordCount;if(isNaN(pRecordCount)){this.log.error(`Entity count did not return a number for [${pEntity}] filtered to [${pMeadowFilterExpression}]... something is fatally wrong from the server accessed in getEntitySet call.`);return fCallback(new Error('Entity count did not return a number in getEntitySet.'));}let tmpDownloadBatchSize=this.options.downloadBatchSize;const tmpPageCount=Math.ceil(tmpRecordCount/tmpDownloadBatchSize);// Build an indexed array of page descriptors to preserve ordering
|
|
6861
6922
|
const tmpPages=[];for(let i=0;i<tmpPageCount;i++){tmpPages.push({Index:i,Begin:i*tmpDownloadBatchSize,Records:null});}// Fetch pages concurrently and reassemble in order.
|
|
6862
6923
|
// Per-call DownloadPageConcurrency overrides the provider-level default.
|
|
6863
6924
|
const tmpPageConcurrency=typeof pOptions.DownloadPageConcurrency==='number'?pOptions.DownloadPageConcurrency:typeof this.options.downloadPageConcurrency==='number'?this.options.downloadPageConcurrency:4;this.fable.Utility.eachLimit(tmpPages,tmpPageConcurrency,(pPage,fDownloadCallback)=>{this._readEntityPage(pEntity,pMeadowFilterExpression,pPage.Begin,tmpDownloadBatchSize,tmpReadOptions,(pDownloadError,pDownloadResponse,pDownloadBody)=>{if(pDownloadResponse&&pDownloadResponse.statusCode&&pDownloadResponse.statusCode>=400){this.log.error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}] [${pPage.Begin}/${tmpDownloadBatchSize}]: ${pDownloadResponse.statusCode} ${pDownloadResponse.statusMessage}`);return fDownloadCallback(new Error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}] [${pPage.Begin}/${tmpDownloadBatchSize}]: ${pDownloadResponse.statusCode} ${JSON.stringify(pDownloadBody||{})}`));}if(Array.isArray(pDownloadBody)){pPage.Records=pDownloadBody;}return fDownloadCallback(pDownloadError);});},pFullDownloadError=>{// Reassemble pages in index order to maintain consistent ordering
|
|
6864
|
-
let tmpEntitySet=[];for(let i=0;i<tmpPages.length;i++){if(Array.isArray(tmpPages[i].Records)){tmpEntitySet=tmpEntitySet.concat(tmpPages[i].Records);}}
|
|
6925
|
+
let tmpEntitySet=[];for(let i=0;i<tmpPages.length;i++){if(Array.isArray(tmpPages[i].Records)){tmpEntitySet=tmpEntitySet.concat(tmpPages[i].Records);}}// Do not cache projected (partial) records — see getEntitySetPage.
|
|
6926
|
+
if(!tmpProjection){if(tmpEntitySet){this.recordSetCache[tmpCacheKey].put(tmpEntitySet,pMeadowFilterExpression);}this.cacheIndividualEntityRecords(pEntity,tmpEntitySet,tmpScope);}return fCallback(pFullDownloadError,tmpEntitySet);});},postfix,pOptions.URLPrefix);}.bind(this));});}////////////////////////////////////////////////////////////////////////////////
|
|
6865
6927
|
// Entity Creation and Update Methods
|
|
6866
6928
|
/**
|
|
6867
6929
|
* @param {string} pEntityType - The type of the entity to format the URL for.
|