pict 1.0.387 → 1.0.388
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/dist/pict.js +134 -25
- 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 +1 -1
- package/source/Pict-Meadow-EntityProvider.js +530 -175
- package/source/filters/Filter.js +3 -1
- package/types/source/Pict-CSS.d.ts +2 -1
- package/types/source/Pict-CSS.d.ts.map +1 -1
- package/types/source/Pict-Meadow-EntityProvider.d.ts +123 -7
- package/types/source/Pict-Meadow-EntityProvider.d.ts.map +1 -1
- package/types/source/filters/Filter.d.ts +7 -2
- package/types/source/filters/Filter.d.ts.map +1 -1
package/dist/pict.js
CHANGED
|
@@ -6218,7 +6218,7 @@ try{if(!global.localStorage)return false;}catch(_){return false;}var val=global.
|
|
|
6218
6218
|
// presumably different callback function.
|
|
6219
6219
|
// This makes sure that own properties are retained, so that
|
|
6220
6220
|
// 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.
|
|
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.388","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://stevenvelozo@github.com/stevenvelozo/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.78","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
6222
|
/* global Pict, _Pict: writeable *//**
|
|
6223
6223
|
* Simple function to load a pict Application
|
|
6224
6224
|
*
|
|
@@ -6435,12 +6435,108 @@ const tmpTargetElement=typeof pAddress==='string'?window.jQuery(pAddress):window
|
|
|
6435
6435
|
*/toggleClass(pAddress,pClass){if(this.hasClass(pAddress,pClass)){this.removeClass(pAddress,pClass);}else{this.addClass(pAddress,pClass);}}}module.exports=PictContentAssignment;},{"fable":68}],197:[function(require,module,exports){const libFableServiceBase=require('fable').ServiceProviderBase;class PictDataProvider extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);/** @type {import('fable') & import('./Pict')} */this.fable;this.serviceType='PictDataProvider';}/**
|
|
6436
6436
|
* @param {string} pAddress - The address of the data to retrieve
|
|
6437
6437
|
* @param {object} [pData] - (optional) The record to provide to the address resolver
|
|
6438
|
-
*/getDataByAddress(pAddress,pData){let tmpData=typeof pData==='undefined'?{}:pData;const tmpAddressSpace={Fable:this.fable,Pict:this.fable,AppData:this.fable.AppData,Bundle:this.fable.Bundle,Record:tmpData};return this.fable.manifest.getValueByHash(tmpAddressSpace,pAddress);}}module.exports=PictDataProvider;},{"fable":68}],198:[function(require,module,exports){const libFableServiceBase=require('fable').ServiceProviderBase
|
|
6438
|
+
*/getDataByAddress(pAddress,pData){let tmpData=typeof pData==='undefined'?{}:pData;const tmpAddressSpace={Fable:this.fable,Pict:this.fable,AppData:this.fable.AppData,Bundle:this.fable.Bundle,Record:tmpData};return this.fable.manifest.getValueByHash(tmpAddressSpace,pAddress);}}module.exports=PictDataProvider;},{"fable":68}],198:[function(require,module,exports){const libFableServiceBase=require('fable').ServiceProviderBase;// Minimum meadow-endpoints version, per major, that serves the body-driven
|
|
6439
|
+
// POST /:Entity/Query read route. The route was added in 2.1.0 and 4.1.0 but
|
|
6440
|
+
// never shipped on the 3.x line or 4.0.x — so support is NOT monotonic across
|
|
6441
|
+
// majors and a flat ">= x" comparison would be wrong. Used only as a fallback
|
|
6442
|
+
// when the server does not advertise an explicit Capabilities flag.
|
|
6443
|
+
const QUERY_ENDPOINT_MIN_VERSION_BY_MAJOR={2:'2.1.0',4:'4.1.0'};class PictMeadowEntityProvider extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){var _this$fable$RestClien;super(pFable,pOptions,pServiceHash);/** @type {any} */this.options;/** @type {import('./Pict') & { settings: any } & { newAnticipate: any }} */this.fable;/** @type {any} */this.log;this.serviceType='PictMeadowProvider';if(this.fable.settings.PictDefaultURLPrefix){this.options.urlPrefix=this.fable.settings.PictDefaultURLPrefix;}else if(!this.options.urlPrefix){this.options.urlPrefix='/1.0/';}if(!this.options.downloadBatchSize){if(typeof this.fable.settings.PictDefaultDownloadBatchSize==='number'){this.options.downloadBatchSize=this.fable.settings.PictDefaultDownloadBatchSize;}else{this.options.downloadBatchSize=100;}}if(typeof this.options.downloadPageConcurrency!=='number'){this.options.downloadPageConcurrency=typeof this.fable.settings.PictDefaultDownloadPageConcurrency==='number'?this.fable.settings.PictDefaultDownloadPageConcurrency:4;}if(typeof this.options.maxBundleConcurrency!=='number'){this.options.maxBundleConcurrency=typeof this.fable.settings.PictDefaultMaxBundleConcurrency==='number'?this.fable.settings.PictDefaultMaxBundleConcurrency:8;}//@ts-ignore - FIXME - remove once we have fable types
|
|
6439
6444
|
this.restClient=(_this$fable$RestClien=this.fable.RestClient)!==null&&_this$fable$RestClien!==void 0?_this$fable$RestClien:this.fable.instantiateServiceProviderWithoutRegistration('RestClient');/** @type {Record<string, import('cachetrax')>} */this.recordCache={};/** @type {Record<string, import('cachetrax')>} */this.recordSetCache={};this.entityColumnTranslations={CreatingIDUser:'User',UpdatingIDUser:'User',DeletingIDUser:'User'};/** @type {(pOptions: Record<string, any>) => Record<string, any>} */this.prepareRequestOptions=pOptions=>{return pOptions;};/**
|
|
6440
6445
|
* After buildBundleWaves() is called by gatherDataFromServer(), this
|
|
6441
6446
|
* property holds the computed wave schedule for inspection/debugging.
|
|
6442
6447
|
* @type {Array<Array<{Index: number, Step: Record<string, any>}>>|null}
|
|
6443
|
-
*/this.lastBundleWaves=null
|
|
6448
|
+
*/this.lastBundleWaves=null;// Master switch for the body-driven POST /:Entity/Query transport. When
|
|
6449
|
+
// false the provider always uses the legacy GET reads (no capability
|
|
6450
|
+
// probe is ever issued). Defaults on; opt out via option or setting.
|
|
6451
|
+
if(typeof this.options.UseQueryEndpoint==='boolean'){this.useQueryEndpoint=this.options.UseQueryEndpoint;}else if(typeof this.fable.settings.PictMeadowUseQueryEndpoint==='boolean'){this.useQueryEndpoint=this.fable.settings.PictMeadowUseQueryEndpoint;}else{this.useQueryEndpoint=true;}/**
|
|
6452
|
+
* Per-(urlPrefix, entity) capability cache. Different entities can resolve
|
|
6453
|
+
* to different backend services (and thus different meadow-endpoints
|
|
6454
|
+
* versions) behind the same urlPrefix, so support is cached per entity.
|
|
6455
|
+
* @type {Record<string, { SupportsQuery: boolean, Metadata: (Record<string, any>|null) }>}
|
|
6456
|
+
*/this.endpointCapabilityCache={};/**
|
|
6457
|
+
* In-flight capability probes, keyed identically to the cache, so
|
|
6458
|
+
* concurrent reads of the same entity collapse onto a single Schema probe.
|
|
6459
|
+
* @type {Record<string, Array<(pError: Error|null, pSupportsQuery: boolean) => void>>}
|
|
6460
|
+
*/this.endpointCapabilityInflight={};}/**
|
|
6461
|
+
* Compute the capability cache key for an (entity, urlPrefix) pair.
|
|
6462
|
+
*
|
|
6463
|
+
* @param {string} pEntity - The entity name.
|
|
6464
|
+
* @param {string} [pURLPrefix] - The URL prefix in play (defaults to the provider default).
|
|
6465
|
+
* @return {string} The cache key.
|
|
6466
|
+
*/_capabilityKey(pEntity,pURLPrefix){return`${pURLPrefix||this.options.urlPrefix}::${pEntity}`;}/**
|
|
6467
|
+
* Major-version-aware check of whether a meadow-endpoints version string
|
|
6468
|
+
* serves the POST /:Entity/Query route. Support is keyed off the major
|
|
6469
|
+
* version (see QUERY_ENDPOINT_MIN_VERSION_BY_MAJOR) because the route was
|
|
6470
|
+
* backported to 2.1.0 and added in 4.1.0, but absent on 3.x and 4.0.x.
|
|
6471
|
+
*
|
|
6472
|
+
* @param {string} pVersion - A semver string (e.g. '4.1.0').
|
|
6473
|
+
* @return {boolean} True if the version is known to serve the Query route.
|
|
6474
|
+
*/isMeadowEndpointsVersionQueryCapable(pVersion){if(typeof pVersion!=='string'){return false;}const tmpParts=pVersion.split('.').map(pPart=>{return parseInt(pPart,10);});if(tmpParts.length<1||isNaN(tmpParts[0])){return false;}const tmpMajor=tmpParts[0];const tmpMinimum=QUERY_ENDPOINT_MIN_VERSION_BY_MAJOR[tmpMajor];if(!tmpMinimum){return false;}const tmpMinimumParts=tmpMinimum.split('.').map(pPart=>{return parseInt(pPart,10);});// Lexicographic compare of [major, minor, patch] with missing parts as 0.
|
|
6475
|
+
for(let i=0;i<3;i++){const tmpHave=isNaN(tmpParts[i])?0:tmpParts[i];const tmpNeed=isNaN(tmpMinimumParts[i])?0:tmpMinimumParts[i];if(tmpHave>tmpNeed){return true;}if(tmpHave<tmpNeed){return false;}}return true;}/**
|
|
6476
|
+
* Decide, from a Schema endpoint response body, whether the serving
|
|
6477
|
+
* meadow-endpoints supports the POST /:Entity/Query route. An explicit
|
|
6478
|
+
* Capabilities flag wins when present; otherwise fall back to a
|
|
6479
|
+
* major-version-aware check of the advertised meadow-endpoints version.
|
|
6480
|
+
* Servers that advertise nothing (older deployments) are unsupported.
|
|
6481
|
+
*
|
|
6482
|
+
* @param {Record<string, any>} pSchemaBody - The Schema endpoint response body.
|
|
6483
|
+
* @return {boolean} True if POST /:Entity/Query is supported.
|
|
6484
|
+
*/evaluateQueryEndpointSupport(pSchemaBody){if(!pSchemaBody||typeof pSchemaBody!=='object'){return false;}const tmpMetadata=pSchemaBody.RetoldMetadata;if(!tmpMetadata||typeof tmpMetadata!=='object'){return false;}if(tmpMetadata.Capabilities&&typeof tmpMetadata.Capabilities.QueryEndpoint==='boolean'){return tmpMetadata.Capabilities.QueryEndpoint;}const tmpVersion=tmpMetadata.PackageVersions&&tmpMetadata.PackageVersions['meadow-endpoints'];if(typeof tmpVersion==='string'){return this.isMeadowEndpointsVersionQueryCapable(tmpVersion);}return false;}/**
|
|
6485
|
+
* Seed the capability cache for an entity from a Schema response the caller
|
|
6486
|
+
* already has in hand (e.g. pict-section-recordset fetches the schema during
|
|
6487
|
+
* initialization). Avoids a redundant capability probe.
|
|
6488
|
+
*
|
|
6489
|
+
* @param {string} pEntity - The entity name.
|
|
6490
|
+
* @param {Record<string, any>} pSchemaBody - The Schema endpoint response body.
|
|
6491
|
+
* @param {string} [pURLPrefix] - The URL prefix the schema was fetched from.
|
|
6492
|
+
* @return {boolean} The resolved support value now cached.
|
|
6493
|
+
*/primeEntityCapabilityFromSchema(pEntity,pSchemaBody,pURLPrefix){const tmpSupportsQuery=this.evaluateQueryEndpointSupport(pSchemaBody);this.endpointCapabilityCache[this._capabilityKey(pEntity,pURLPrefix)]={SupportsQuery:tmpSupportsQuery,Metadata:pSchemaBody&&pSchemaBody.RetoldMetadata||null};return tmpSupportsQuery;}/**
|
|
6494
|
+
* Resolve whether POST /:Entity/Query is usable for an entity, probing the
|
|
6495
|
+
* Schema endpoint once and caching the result per (urlPrefix, entity).
|
|
6496
|
+
* Concurrent calls for the same key collapse onto a single probe.
|
|
6497
|
+
*
|
|
6498
|
+
* Probe failures (network/parse) are NOT cached — they resolve to false (GET
|
|
6499
|
+
* fallback) for this call but allow a later retry, so a transient blip does
|
|
6500
|
+
* not permanently disable the faster transport for the session. A successful
|
|
6501
|
+
* probe of an older server (no metadata) caches false and never re-probes.
|
|
6502
|
+
*
|
|
6503
|
+
* @param {string} pEntity - The entity name.
|
|
6504
|
+
* @param {string} pURLPrefix - The URL prefix in play.
|
|
6505
|
+
* @param {(pError: Error|null, pSupportsQuery: boolean) => void} fCallback - Completion callback.
|
|
6506
|
+
* @return {void}
|
|
6507
|
+
*/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
|
+
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);}});}/**
|
|
6509
|
+
* Build the POST /:Entity/Query request body for a filtered read.
|
|
6510
|
+
*
|
|
6511
|
+
* @param {string} pMeadowFilterExpression - The meadow filter string (may be empty).
|
|
6512
|
+
* @param {number|null} [pBegin] - Pagination start cursor.
|
|
6513
|
+
* @param {number|null} [pCap] - Pagination page size.
|
|
6514
|
+
* @param {Record<string, any>} [pProjection] - Optional { Mode:'LiteExtended', ExtraColumns:[...] }.
|
|
6515
|
+
* @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;}if(pProjection&&pProjection.Mode==='LiteExtended'&&Array.isArray(pProjection.ExtraColumns)&&pProjection.ExtraColumns.length>0){// LiteExtended GET maps to a Lite read carrying ExtraColumns on Query.
|
|
6517
|
+
tmpBody.Lite=true;tmpBody.ExtraColumns=pProjection.ExtraColumns.join(',');}return tmpBody;}/**
|
|
6518
|
+
* Read a page of an entity set, using POST /:Entity/Query when supported and
|
|
6519
|
+
* falling back to the legacy GET read otherwise. The callback mirrors
|
|
6520
|
+
* restClient.getJSON exactly: (pError, pResponse, pBody).
|
|
6521
|
+
*
|
|
6522
|
+
* @param {string} pEntity - The entity name.
|
|
6523
|
+
* @param {string} pMeadowFilterExpression - The meadow filter string (may be empty).
|
|
6524
|
+
* @param {number|null} pBegin - Pagination start cursor (null for unpaged).
|
|
6525
|
+
* @param {number|null} pCap - Pagination page size (null for unpaged).
|
|
6526
|
+
* @param {Record<string, any>} pReadOptions - { SupportsQuery, URLPrefix, Postfix, Projection }.
|
|
6527
|
+
* @param {(pError: Error|null, pResponse: any, pBody: any) => void} fCallback - Completion callback.
|
|
6528
|
+
* @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 tmpProjectionStanza=tmpProjection&&tmpProjection.Mode==='LiteExtended'&&Array.isArray(tmpProjection.ExtraColumns)&&tmpProjection.ExtraColumns.length>0?`/LiteExtended/${tmpProjection.ExtraColumns.join(',')}`:'';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
|
+
* Read the count of an entity set, using POST /:Entity/Query (Count mode)
|
|
6531
|
+
* when supported and the legacy GET Count otherwise. The callback mirrors
|
|
6532
|
+
* restClient.getJSON: (pError, pResponse, pBody) where pBody carries .Count.
|
|
6533
|
+
*
|
|
6534
|
+
* @param {string} pEntity - The entity name.
|
|
6535
|
+
* @param {string} pMeadowFilterExpression - The meadow filter string (may be empty).
|
|
6536
|
+
* @param {Record<string, any>} pReadOptions - { SupportsQuery, URLPrefix, Postfix }.
|
|
6537
|
+
* @param {(pError: Error|null, pResponse: any, pBody: any) => void} fCallback - Completion callback.
|
|
6538
|
+
* @return {void}
|
|
6539
|
+
*/_readEntityCount(pEntity,pMeadowFilterExpression,pReadOptions,fCallback){const tmpURLPrefix=pReadOptions&&pReadOptions.URLPrefix||this.options.urlPrefix;const tmpPostfix=pReadOptions&&pReadOptions.Postfix||'';if(pReadOptions&&pReadOptions.SupportsQuery){const tmpBody=this._buildQueryReadBody(pMeadowFilterExpression,null,null,null);tmpBody.Count=true;const tmpRequestOptions={url:`${tmpURLPrefix}${pEntity}s/Query${tmpPostfix}`,body:tmpBody};return this.restClient.postJSON(tmpRequestOptions,fCallback);}const tmpFilterStanza=pMeadowFilterExpression?`/FilteredTo/${pMeadowFilterExpression}`:'';const tmpURL=`${tmpURLPrefix}${pEntity}s/Count${tmpFilterStanza}${tmpPostfix}`;return this.restClient.getJSON(tmpURL,fCallback);}/**
|
|
6444
6540
|
* Compute the cache bucket key for an entity, optionally namespaced by a scope.
|
|
6445
6541
|
* A non-empty scope yields an isolated bucket (`Entity::Scope`) so scoped/partial
|
|
6446
6542
|
* (e.g. Lite) records never touch the global `Entity` cache that full-record
|
|
@@ -6534,7 +6630,7 @@ this.fable.manifest.setValueByHash(tmpDestinationEntity,tmpBucketAddress,tmpSour
|
|
|
6534
6630
|
*
|
|
6535
6631
|
* @param {Record<string, any>} pConfiguration - The configuration object for the dataset projection.
|
|
6536
6632
|
* @param {Record<string, any>} pContext - The context object to use when parsing the record prototype template and resolving the output recordset address mapping.
|
|
6537
|
-
*/projectDataset(pConfiguration,pContext){let tmpInputRecordset=this.fable.manifest.getValueByHash(pContext,pConfiguration.InputRecordsetAddress);if(
|
|
6633
|
+
*/projectDataset(pConfiguration,pContext){let tmpInputRecordset=this.fable.manifest.getValueByHash(pContext,pConfiguration.InputRecordsetAddress);if(tmpInputRecordset==null||typeof tmpInputRecordset!=='object'){throw new Error(`EntityBundleRequest failed to project dataset because the input recordset [${pConfiguration.InputRecordsetAddress}] did not return an valid object.`);}if(!Array.isArray(tmpInputRecordset)){tmpInputRecordset=[tmpInputRecordset];}let tmpDefaultOutputRecordset=this.fable.manifest.getValueByHash(pContext,pConfiguration.OutputRecordsetAddress);if(!tmpDefaultOutputRecordset){tmpDefaultOutputRecordset=[];this.fable.manifest.setValueByHash(pContext,pConfiguration.OutputRecordsetAddress,tmpDefaultOutputRecordset);}for(const tmpInputRecord of tmpInputRecordset){let tmpOutputRecordset=tmpDefaultOutputRecordset;let tmpOutputRecordsetAddressOverride;if(typeof pConfiguration.OutputRecordsetAddressMapping==='object'){tmpOutputRecordsetAddressOverride=this._resolveOutputRecordsetAddressMapping(pConfiguration,pContext,tmpInputRecord);if(tmpOutputRecordsetAddressOverride){tmpOutputRecordset=this.fable.manifest.getValueByHash(pContext,tmpOutputRecordsetAddressOverride);if(!tmpOutputRecordset){tmpOutputRecordset=[];this.fable.manifest.setValueByHash(pContext,tmpOutputRecordsetAddressOverride,tmpOutputRecordset);}}if(!tmpOutputRecordset||!Array.isArray(tmpOutputRecordset)){tmpOutputRecordset=tmpDefaultOutputRecordset;}}const tmpPrototypeAddress=this.fable.parseTemplate(pConfiguration.RecordPrototypeAddress,Object.assign({InputRecord:tmpInputRecord},pContext));const tmpRecordPrototype=this.fable.manifest.getValueByHash(Object.assign({InputRecord:tmpInputRecord,OutputRecordset:tmpOutputRecordset},pContext),tmpPrototypeAddress);let tmpOutputRecord={};if(Array.isArray(tmpRecordPrototype)&&tmpRecordPrototype.length>0){tmpOutputRecord=tmpRecordPrototype[0];}else{tmpOutputRecordset.push(tmpOutputRecord);}let tmpRecordFieldMapping=pConfiguration.RecordFieldMapping[tmpOutputRecordsetAddressOverride]||pConfiguration.RecordFieldMapping.Default;if(!tmpRecordFieldMapping){tmpRecordFieldMapping=pConfiguration.RecordFieldMapping[Object.keys(pConfiguration.RecordFieldMapping)[0]];}if(!tmpRecordFieldMapping){throw new Error(`EntityBundleRequest failed to project dataset because the record field mapping for [${tmpOutputRecordsetAddressOverride}] did not return a mapping.`);}for(const tmpInputFieldAddress of Object.keys(tmpRecordFieldMapping)){const tmpOutputFieldAddress=tmpRecordFieldMapping[tmpInputFieldAddress];const tmpInputFieldValue=this.fable.manifest.getValueByHash(Object.assign({InputRecord:tmpInputRecord},pContext),tmpInputFieldAddress);this.fable.manifest.setValueByHash(Object.assign({OutputRecord:tmpOutputRecord},pContext),tmpOutputFieldAddress,tmpInputFieldValue);}}}/**
|
|
6538
6634
|
* @param {Record<string, any>} pConfiguration - The configuration object for the dataset projection.
|
|
6539
6635
|
* @param {Record<string, any>} pContext - The context object to use when resolving the output recordset address mapping.
|
|
6540
6636
|
* @param {Record<string, any>} pInputRecord - The input record to use when resolving the output recordset address mapping.
|
|
@@ -6663,18 +6759,28 @@ this.recordCache[tmpCacheKey].prune(()=>{});// First pass: gather IDs to fetch
|
|
|
6663
6759
|
for(const tmpRecord of pRecordSet){const tmpIDValue=tmpRecord[tmpEntityIDSourceField];if(tmpIDValue){const tmpCachedRecord=this.recordCache[tmpCacheKey].read(tmpIDValue);if(!tmpCachedRecord){tmpEntityIDsToFetch.add(tmpIDValue);}}}// Now if there are records to fetch, do the request.
|
|
6664
6760
|
if(tmpEntityIDsToFetch.size>0){tmpAnticipate.anticipate(function(fRequestComplete){const tmpIDRecordsArray=Array.from(tmpEntityIDsToFetch);this.getEntitySetByIDListChunked(tmpEntityName,tmpIDRecordsArray,{NoCount:true,Scope:pScope},fRequestComplete);}.bind(this));}}tmpAnticipate.wait(pError=>{if(pError){this.log.error(`cacheConnectedEntityRecords error gathering connected entity records: ${pError}`,{Stack:pError.stack});return fCallback(pError);}return fCallback();});}/**
|
|
6665
6761
|
* Fetch a set of entity records by primary-key ID list, chunking the meadow IN
|
|
6666
|
-
* filter
|
|
6667
|
-
*
|
|
6668
|
-
*
|
|
6669
|
-
*
|
|
6762
|
+
* filter into requests.
|
|
6763
|
+
*
|
|
6764
|
+
* Chunk size is capability-aware: the legacy GET read embeds the IN-list in
|
|
6765
|
+
* the URL, so it is chunked small (ConnectedEntityIDChunkSize, default 200) to
|
|
6766
|
+
* keep the URL under HTTP/2 header-size limits — oversized URLs trip a
|
|
6767
|
+
* connection-level reset that takes sibling multiplexed requests down with it.
|
|
6768
|
+
* When the endpoint serves POST /:Entity/Query the IN-list rides in the body
|
|
6769
|
+
* (no URI limit), so a much larger chunk is used (ConnectedEntityIDQueryChunkSize,
|
|
6770
|
+
* default 5000) — bounding response size rather than URL length, and collapsing
|
|
6771
|
+
* what used to be many small requests into one (or a few). Records are cached
|
|
6772
|
+
* as a side effect of getEntitySet; the callback returns no data.
|
|
6670
6773
|
*
|
|
6671
6774
|
* @param {string} pEntityName - The entity name (e.g. 'Project').
|
|
6672
6775
|
* @param {Array<number|string>} pIDRecordsArray - The primary-key IDs to fetch.
|
|
6673
|
-
* @param {Object} pOptions - Options passed through to getEntitySet (Scope, NoCount, etc).
|
|
6776
|
+
* @param {Object} pOptions - Options passed through to getEntitySet (Scope, NoCount, URLPrefix, etc).
|
|
6674
6777
|
* @param {(error?: Error) => void} fCallback - Completion callback.
|
|
6675
6778
|
*
|
|
6676
6779
|
* @return {void}
|
|
6677
|
-
*/getEntitySetByIDListChunked(pEntityName,pIDRecordsArray,pOptions,fCallback){if(!Array.isArray(pIDRecordsArray)||pIDRecordsArray.length<1){return fCallback();}const
|
|
6780
|
+
*/getEntitySetByIDListChunked(pEntityName,pIDRecordsArray,pOptions,fCallback){if(!Array.isArray(pIDRecordsArray)||pIDRecordsArray.length<1){return fCallback();}const tmpOptions=pOptions||{};// Resolve transport capability once (cached; getEntitySet reuses it) so the
|
|
6781
|
+
// chunk size matches the transport. The probe URL prefix matches the one
|
|
6782
|
+
// getEntitySet will read from tmpOptions.URLPrefix.
|
|
6783
|
+
this.resolveEntityQuerySupport(pEntityName,tmpOptions.URLPrefix,(pSupportError,pSupportsQuery)=>{const tmpChunkSize=pSupportsQuery?this.options&&this.options.ConnectedEntityIDQueryChunkSize||5000:this.options&&this.options.ConnectedEntityIDChunkSize||200;const tmpAnticipate=this.fable.newAnticipate();for(let i=0;i<pIDRecordsArray.length;i+=tmpChunkSize){const tmpIDChunk=pIDRecordsArray.slice(i,i+tmpChunkSize);tmpAnticipate.anticipate(function(fChunkComplete){const tmpMeadowFilterExpression=`FBL~ID${pEntityName}~INN~${tmpIDChunk.join(',')}`;this.getEntitySet(pEntityName,tmpMeadowFilterExpression,pError=>{if(pError){this.log.error(`getEntitySetByIDListChunked error getting connected entity records for [${pEntityName}] with IDs [${tmpIDChunk.join(',')}]: ${pError}`,{Stack:pError.stack});return fChunkComplete(pError);}return fChunkComplete();},null,tmpOptions);}.bind(this));}tmpAnticipate.wait(fCallback);});}/**
|
|
6678
6784
|
* For a given list of objects, cache connected entity records.
|
|
6679
6785
|
*
|
|
6680
6786
|
* @param {Array} pRecordSet - An array of objects to check cache on joined records for, and, get/cache the records as needed.
|
|
@@ -6709,22 +6815,22 @@ const tmpSpeculativeRecordIDColumn=`ID${pEntity}`;if(tmpEntitySet[0]&&typeof tmp
|
|
|
6709
6815
|
* @param {string} [postfix] - Optional, adds a postfix string to the url.
|
|
6710
6816
|
* @param {string} [pURLPrefix] - Optional per-request URL prefix; overrides the provider default (e.g. a private-data-lake route).
|
|
6711
6817
|
* @param {Record<string, any>} [pOptions] - Optional { Scope, Projection }: cache scope and Lite/LiteExtended projection.
|
|
6712
|
-
*/getEntitySetPage(pEntity,pMeadowFilterExpression,pRecordStartCursor,pRecordCount,fCallback){let postfix=arguments.length>5&&arguments[5]!==undefined?arguments[5]:'';let pURLPrefix=arguments.length>6&&arguments[6]!==undefined?arguments[6]:'';let pOptions=arguments.length>7&&arguments[7]!==undefined?arguments[7]:{};const
|
|
6818
|
+
*/getEntitySetPage(pEntity,pMeadowFilterExpression,pRecordStartCursor,pRecordCount,fCallback){let postfix=arguments.length>5&&arguments[5]!==undefined?arguments[5]:'';let pURLPrefix=arguments.length>6&&arguments[6]!==undefined?arguments[6]:'';let pOptions=arguments.length>7&&arguments[7]!==undefined?arguments[7]:{};const tmpScope=pOptions&&pOptions.Scope?pOptions.Scope:'';// Per-request URL prefix override (positional, e.g. a private-data-lake route);
|
|
6819
|
+
// also accepted via pOptions.URLPrefix. Falls back to the provider default.
|
|
6820
|
+
const tmpURLPrefix=pURLPrefix||pOptions&&pOptions.URLPrefix||this.options.urlPrefix;// LiteExtended projection: fetch only ID/GUID/owner/update + the requested
|
|
6713
6821
|
// ExtraColumns (drops blob columns). Used by scoped list fetches to avoid the
|
|
6714
6822
|
// heavy full-record payload.
|
|
6715
|
-
const
|
|
6716
|
-
// also accepted via pOptions.URLPrefix. Falls back to the provider default.
|
|
6717
|
-
const tmpURLPrefix=pURLPrefix||pOptions&&pOptions.URLPrefix||this.options.urlPrefix;const tmpURL=`${tmpURLPrefix}${pEntity}s${tmpProjectionStanza}${tmpFilterStanza}/${pRecordStartCursor}/${pRecordCount}`;return this.restClient.getJSON(tmpURL+(postfix||''),function(pDownloadError,pDownloadResponse,pDownloadBody){if(pDownloadResponse&&pDownloadResponse.statusCode&&pDownloadResponse.statusCode>=400){this.log.error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}] [${pRecordStartCursor}/${pRecordCount}] from url [${tmpURL}]: ${pDownloadResponse.statusCode} ${pDownloadResponse.statusMessage}`);return fCallback(new Error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}] [${pRecordStartCursor}/${pRecordCount}] from url [${tmpURL}]: ${pDownloadResponse.statusCode} ${JSON.stringify(pDownloadBody||{})}`));}// Do not cache projected (Lite/partial) records in the entity cache — a
|
|
6823
|
+
const tmpProjection=pOptions&&pOptions.Projection?pOptions.Projection:null;this.resolveEntityQuerySupport(pEntity,tmpURLPrefix,(pSupportError,pSupportsQuery)=>{this._readEntityPage(pEntity,pMeadowFilterExpression,pRecordStartCursor,pRecordCount,{SupportsQuery:pSupportsQuery,URLPrefix:tmpURLPrefix,Postfix:postfix||'',Projection:tmpProjection},(pDownloadError,pDownloadResponse,pDownloadBody)=>{if(pDownloadResponse&&pDownloadResponse.statusCode&&pDownloadResponse.statusCode>=400){this.log.error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}] [${pRecordStartCursor}/${pRecordCount}]: ${pDownloadResponse.statusCode} ${pDownloadResponse.statusMessage}`);return fCallback(new Error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}] [${pRecordStartCursor}/${pRecordCount}]: ${pDownloadResponse.statusCode} ${JSON.stringify(pDownloadBody||{})}`));}// Do not cache projected (Lite/partial) records in the entity cache — a
|
|
6718
6824
|
// partial record would shadow the full record for other consumers
|
|
6719
6825
|
// (row-click View, {~E:~}). Projected fetches are rendered straight from
|
|
6720
6826
|
// the list state and never need to be in the entity cache.
|
|
6721
|
-
if(!
|
|
6827
|
+
if(!tmpProjection){this.cacheIndividualEntityRecords(pEntity,pDownloadBody,tmpScope);}return fCallback(pDownloadError,pDownloadBody);});});}/**
|
|
6722
6828
|
* @param {string} pEntity - The name of the entity to get the count of.
|
|
6723
6829
|
* @param {string} pMeadowFilterExpression - The meadow filter expression to filter the entity set by.
|
|
6724
6830
|
* @param {(pError?: Error, pRecordCount?: number) => void} fCallback - The callback function to call when the operation is complete.
|
|
6725
6831
|
* @param {string} [postfix] - Optional, adds a postfix string to the count url
|
|
6726
6832
|
* @param {string} [pURLPrefix] - Optional per-request URL prefix; overrides the provider default.
|
|
6727
|
-
*/getEntitySetRecordCount(pEntity,pMeadowFilterExpression,fCallback){let postfix=arguments.length>3&&arguments[3]!==undefined?arguments[3]:'';let pURLPrefix=arguments.length>4&&arguments[4]!==undefined?arguments[4]:'';
|
|
6833
|
+
*/getEntitySetRecordCount(pEntity,pMeadowFilterExpression,fCallback){let postfix=arguments.length>3&&arguments[3]!==undefined?arguments[3]:'';let pURLPrefix=arguments.length>4&&arguments[4]!==undefined?arguments[4]:'';this.resolveEntityQuerySupport(pEntity,pURLPrefix,(pSupportError,pSupportsQuery)=>{this._readEntityCount(pEntity,pMeadowFilterExpression,{SupportsQuery:pSupportsQuery,URLPrefix:pURLPrefix||'',Postfix:postfix||''},(pError,pResponse,pBody)=>{if(pResponse&&pResponse.statusCode&&pResponse.statusCode>=400){this.log.error(`Error getting entity count of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${pResponse.statusCode} ${pResponse.statusMessage}`);return fCallback(new Error(`Error getting entity count of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${pResponse.statusCode} ${JSON.stringify(pBody||{})}`));}if(pError){this.log.error(`Error getting entity count of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${pError}`);return fCallback(pError);}let tmpRecordCount=0;if(pBody&&pBody.Count){tmpRecordCount=pBody.Count;}return fCallback(pError,tmpRecordCount);});});}/**
|
|
6728
6834
|
* @param {string} pEntity - The name of the entity to get.
|
|
6729
6835
|
* @param {string} pMeadowFilterExpression - The meadow filter expression to filter the entity set by.
|
|
6730
6836
|
* @param {(pError?: Error, pEntitySet?: Array<Record<string, any>>) => void} fCallback - The callback function to call when the operation is complete.
|
|
@@ -6740,17 +6846,18 @@ else if(tmpColumnName in this.entityColumnTranslations){tmpIDColumnsToCache.push
|
|
|
6740
6846
|
* @param {Record<string, any>} [pOptions] - Optional, per-call options (e.g. { DownloadPageConcurrency: 1 }).
|
|
6741
6847
|
*
|
|
6742
6848
|
* @return {void}
|
|
6743
|
-
*/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
|
|
6744
|
-
//
|
|
6745
|
-
//
|
|
6746
|
-
|
|
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
|
|
6850
|
+
// page share the same SupportsQuery flag). The legacy GET reads embed the
|
|
6851
|
+
// filter (and any large IN-list) in the URI, which is exactly the long-URI
|
|
6852
|
+
// 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.
|
|
6747
6854
|
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.
|
|
6748
6855
|
// Does not respect parallelization.
|
|
6749
|
-
const pageSize=250;let page=0;let returnSet=[];const
|
|
6750
|
-
const tmpPages=[];for(let i=0;i<tmpPageCount;i++){tmpPages.push({Index:i,
|
|
6856
|
+
const pageSize=250;let page=0;let returnSet=[];const recursiveCallback=(pDownloadError,pDownloadResponse,pDownloadBody)=>{if(pDownloadResponse&&pDownloadResponse.statusCode&&pDownloadResponse.statusCode>=400||!Array.isArray(pDownloadBody)){this.log.error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${pDownloadResponse.statusCode} ${pDownloadResponse.statusMessage}`);return fCallback(new Error(`Error getting entity set of [${pEntity}] filtered to [${pMeadowFilterExpression}]: ${pDownloadResponse.statusCode} ${JSON.stringify(pDownloadBody||{})}`),[]);}returnSet=returnSet.concat(pDownloadBody);if((pDownloadBody===null||pDownloadBody===void 0?void 0:pDownloadBody.length)<pageSize){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
|
|
6857
|
+
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.
|
|
6751
6858
|
// Per-call DownloadPageConcurrency overrides the provider-level default.
|
|
6752
|
-
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.
|
|
6753
|
-
let tmpEntitySet=[];for(let i=0;i<tmpPages.length;i++){if(Array.isArray(tmpPages[i].Records)){tmpEntitySet=tmpEntitySet.concat(tmpPages[i].Records);}}if(tmpEntitySet){this.recordSetCache[tmpCacheKey].put(tmpEntitySet,pMeadowFilterExpression);}this.cacheIndividualEntityRecords(pEntity,tmpEntitySet,tmpScope);return fCallback(pFullDownloadError,tmpEntitySet);});},postfix,pOptions.URLPrefix);}.bind(this));}////////////////////////////////////////////////////////////////////////////////
|
|
6859
|
+
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
|
|
6860
|
+
let tmpEntitySet=[];for(let i=0;i<tmpPages.length;i++){if(Array.isArray(tmpPages[i].Records)){tmpEntitySet=tmpEntitySet.concat(tmpPages[i].Records);}}if(tmpEntitySet){this.recordSetCache[tmpCacheKey].put(tmpEntitySet,pMeadowFilterExpression);}this.cacheIndividualEntityRecords(pEntity,tmpEntitySet,tmpScope);return fCallback(pFullDownloadError,tmpEntitySet);});},postfix,pOptions.URLPrefix);}.bind(this));});}////////////////////////////////////////////////////////////////////////////////
|
|
6754
6861
|
// Entity Creation and Update Methods
|
|
6755
6862
|
/**
|
|
6756
6863
|
* @param {string} pEntityType - The type of the entity to format the URL for.
|
|
@@ -7336,7 +7443,9 @@ return this.contentMap[pAddress];}this.pict.log.warn(`Mock read from Address ${p
|
|
|
7336
7443
|
* PreparedFilters: Array<PreparedFilter>,
|
|
7337
7444
|
* BundleConfig?: Array<Record<string, any>>,
|
|
7338
7445
|
* UserFilters?: Array<string>,
|
|
7339
|
-
* Postfix?: string
|
|
7446
|
+
* Postfix?: string,
|
|
7447
|
+
* Scope?: string,
|
|
7448
|
+
* Projection?: Record<string, any>,
|
|
7340
7449
|
* }} FilterState
|
|
7341
7450
|
*
|
|
7342
7451
|
* @typedef { 'None' |
|