diff --git a/ci/tests/typesCompile.test.js b/ci/tests/typesCompile.test.js new file mode 100644 index 00000000..9ef4b398 --- /dev/null +++ b/ci/tests/typesCompile.test.js @@ -0,0 +1,84 @@ +/* ********************************************************************* + * This Original Work is copyright of 51 Degrees Mobile Experts Limited. + * Copyright 2026 51 Degrees Mobile Experts Limited, Davidson House, + * Forbury Square, Reading, Berkshire, United Kingdom RG1 3EU. + * + * This Original Work is licensed under the European Union Public Licence + * (EUPL) v.1.2 and is subject to its terms as set out below. + * + * If a copy of the EUPL was not distributed with this file, You can obtain + * one at https://opensource.org/licenses/EUPL-1.2. + * + * The 'Compatible Licences' set out in the Appendix to the EUPL (as may be + * amended by the European Commission) shall be deemed incompatible for + * the purposes of the Work and the provisions of the compatibility + * clause in Article 5 of the EUPL shall not apply. + * + * If using the Work as, or as part of, a network application, by + * including the attribution notice(s) required under Article 5 of the EUPL + * in the end user terms of the application under an appropriate heading, + * such notice(s) shall fulfill the requirements of that article. + * ********************************************************************* */ + +// Compiles a TypeScript file that imports every package with types by its +// package name, as a caller does, with the type files themselves checked. +// The file exists only in memory, at the repository root, so the packages +// resolve through the workspace links in node_modules. + +const path = require('path'); +const ts = require('typescript'); + +const ROOT = path.resolve(__dirname, '..', '..'); +const CHECK_FILE = path.join(ROOT, 'types-compile-check.ts'); +const COMPILE_TIMEOUT_MS = 120000; + +const OPTIONS = { + noEmit: true, + skipLibCheck: false, + esModuleInterop: true, + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ES2020, + moduleResolution: ts.ModuleResolutionKind.Node10 +}; + +const packagesWithTypes = () => + require(path.join(ROOT, 'package.json')).workspaces + .map((folder) => require(path.join(ROOT, folder, 'package.json'))) + .filter((manifest) => manifest.types || manifest.typings) + .map((manifest) => manifest.name); + +const isCheckFile = (fileName) => + path.resolve(fileName).toLowerCase() === CHECK_FILE.toLowerCase(); + +const compile = (source) => { + const host = ts.createCompilerHost(OPTIONS); + const { fileExists, readFile, getSourceFile } = host; + host.fileExists = (fileName) => + isCheckFile(fileName) || fileExists.call(host, fileName); + host.readFile = (fileName) => + isCheckFile(fileName) ? source : readFile.call(host, fileName); + host.getSourceFile = (fileName, language, ...rest) => + isCheckFile(fileName) + ? ts.createSourceFile(fileName, source, language) + : getSourceFile.call(host, fileName, language, ...rest); + const program = ts.createProgram([CHECK_FILE], OPTIONS, host); + const formatHost = { + getCanonicalFileName: (fileName) => fileName, + getCurrentDirectory: () => ROOT, + getNewLine: () => '\n' + }; + return ts.getPreEmitDiagnostics(program) + .map((diagnostic) => ts.formatDiagnostic(diagnostic, formatHost).trim()); +}; + +describe('published types', () => { + test('every package\'s types compile when a TypeScript caller imports ' + + 'them', () => { + const names = packagesWithTypes(); + expect(names.length).toBeGreaterThan(0); + const source = names + .map((name, i) => `import * as p${i} from '${name}';\nexport { p${i} };`) + .join('\n'); + expect(compile(source)).toEqual([]); + }, COMPILE_TIMEOUT_MS); +}); diff --git a/device-detection/fiftyone.devicedetection.cloud/index.js b/device-detection/fiftyone.devicedetection.cloud/index.js index 8677918d..d79524c2 100644 --- a/device-detection/fiftyone.devicedetection.cloud/index.js +++ b/device-detection/fiftyone.devicedetection.cloud/index.js @@ -23,6 +23,6 @@ module.exports = { DeviceDetectionCloud: require('./deviceDetectionCloud'), DeviceDetectionCloudPipelineBuilder: require('./deviceDetectionCloudPipelineBuilder'), - HardwareProfileCloudEngine: require('../fiftyone.devicedetection.cloud/hardwareProfileCloudEngine') + HardwareProfileCloudEngine: require('./hardwareProfileCloudEngine') }; diff --git a/device-detection/fiftyone.devicedetection.cloud/types/deviceDetectionCloudPipelineBuilder.d.ts b/device-detection/fiftyone.devicedetection.cloud/types/deviceDetectionCloudPipelineBuilder.d.ts index bddcc16d..4f4e72bf 100644 --- a/device-detection/fiftyone.devicedetection.cloud/types/deviceDetectionCloudPipelineBuilder.d.ts +++ b/device-detection/fiftyone.devicedetection.cloud/types/deviceDetectionCloudPipelineBuilder.d.ts @@ -12,15 +12,15 @@ declare class DeviceDetectionCloudPipelineBuilder extends DeviceDetectionCloudPi * @param {object} options the options for the pipeline builder * @param {string} options.licenceKeys license key(s) used by the * data file update service. A key can be obtained from the - * 51Degrees website: https://51degrees.com/pricing. + * 51Degrees website: https://51degrees.com/pricing?utm_source=code&utm_medium=comment&utm_campaign=51degrees-node&utm_content=fiftyone.devicedetection.cloud-devicedetectioncloudpipelinebuilder.js&utm_term=constructor. * This parameter MUST be set when using a data file. * If you do not wish to use a key then you can specify * an empty string, but this will cause automatic updates * to be disabled. - * @param {string} options.resourceKey resourceKey * @param {Array|string} options.requestedProperties the fully * qualified names of the properties to ask the cloud service for, such * as device.ismobile. Required with a license key and no resource key. + * @param {string} options.resourceKey resourceKey * @param {number} options.cacheSize size of the default cache * (includes cache if set). * @param {string} options.cloudEndPoint Choose a non default endpoint @@ -36,8 +36,8 @@ declare class DeviceDetectionCloudPipelineBuilder extends DeviceDetectionCloudPi */ constructor({ licenceKeys, resourceKey, requestedProperties, cacheSize, cloudEndPoint, cloudRequestOrigin }: { licenceKeys: string; - resourceKey: string; requestedProperties: Array | string; + resourceKey: string; cacheSize: number; cloudEndPoint: string; cloudRequestOrigin: string; diff --git a/device-detection/fiftyone.devicedetection.cloud/types/index.d.ts b/device-detection/fiftyone.devicedetection.cloud/types/index.d.ts index d1da43e0..c0c0026a 100644 --- a/device-detection/fiftyone.devicedetection.cloud/types/index.d.ts +++ b/device-detection/fiftyone.devicedetection.cloud/types/index.d.ts @@ -1,3 +1,3 @@ export let DeviceDetectionCloud: typeof import("./deviceDetectionCloud"); export let DeviceDetectionCloudPipelineBuilder: typeof import("./deviceDetectionCloudPipelineBuilder"); -export let HardwareProfileCloudEngine: typeof import("../fiftyone.devicedetection.cloud/hardwareProfileCloudEngine"); +export let HardwareProfileCloudEngine: typeof import("./hardwareProfileCloudEngine"); diff --git a/device-detection/fiftyone.devicedetection.onpremise/index.js b/device-detection/fiftyone.devicedetection.onpremise/index.js index 2c4c2058..e5bf84c9 100644 --- a/device-detection/fiftyone.devicedetection.onpremise/index.js +++ b/device-detection/fiftyone.devicedetection.onpremise/index.js @@ -24,5 +24,5 @@ module.exports = { DeviceDetectionOnPremise: require('./deviceDetectionOnPremise'), DeviceDetectionOnPremisePipelineBuilder: require('./deviceDetectionOnPremisePipelineBuilder'), SwigData: require('./swigData'), - swigHelpers: require('../fiftyone.devicedetection.onpremise/swigHelpers') + swigHelpers: require('./swigHelpers') }; diff --git a/device-detection/fiftyone.devicedetection.onpremise/types/deviceDetectionOnPremise.d.ts b/device-detection/fiftyone.devicedetection.onpremise/types/deviceDetectionOnPremise.d.ts index 1de6cead..808c56a1 100644 --- a/device-detection/fiftyone.devicedetection.onpremise/types/deviceDetectionOnPremise.d.ts +++ b/device-detection/fiftyone.devicedetection.onpremise/types/deviceDetectionOnPremise.d.ts @@ -69,7 +69,8 @@ declare class DeviceDetectionOnPremise extends DeviceDetectionOnPremise_base { * @param {string} options.tempDataDir The directory to use for the * temporary data copy if 'createTempDataCopy' is set to true. * @param {boolean} options.updateOnStart whether to download / update - * the datafile on initialisation + * the datafile on initialisation. If there is no file at dataFilePath it + * is downloaded, and processing fails if the download does not work. */ constructor({ dataFilePath, autoUpdate, cache, dataUpdateUrl, dataUpdateVerifyMd5, dataUpdateUseUrlFormatter, restrictedProperties, licenceKeys, download, performanceProfile, reuseTempFile, updateMatchedUserAgent, maxMatchedUserAgentLength, drift, difference, concurrency, allowUnmatched, fileSystemWatcher, pollingInterval, updateTimeMaximumRandomisation, createTempDataCopy, tempDataDir, updateOnStart }: { dataFilePath: string; diff --git a/device-detection/fiftyone.devicedetection.shared/types/index.d.ts b/device-detection/fiftyone.devicedetection.shared/types/index.d.ts index ab18f82a..a385f904 100644 --- a/device-detection/fiftyone.devicedetection.shared/types/index.d.ts +++ b/device-detection/fiftyone.devicedetection.shared/types/index.d.ts @@ -22,16 +22,8 @@ export let testConstants: { hardwareResourceKeyEnvVar: string; browserResourceKeyEnvVar: string; noSetHeaderResourceKeyEnvVar: string; - /** - * @deprecated No test reads a licence key under this name. The licence - * key is read from the _51DEGREES_LICENSE_KEY environment variable. - */ licenseKeyEnvVar: string; }; - /** - * @deprecated The name each of envVars replaced. An old name is read only - * when the name that replaced it is unset or empty. Use envVars. - */ legacyEnvVars: { _51DEGREES_RESOURCE_KEY: string; _51DEGREES_RESOURCE_KEY_SUPER: string; diff --git a/device-detection/fiftyone.devicedetection.shared/types/lib/testConstants.d.ts b/device-detection/fiftyone.devicedetection.shared/types/lib/testConstants.d.ts index 2b20d556..f893efa6 100644 --- a/device-detection/fiftyone.devicedetection.shared/types/lib/testConstants.d.ts +++ b/device-detection/fiftyone.devicedetection.shared/types/lib/testConstants.d.ts @@ -5,16 +5,8 @@ export namespace envVars { let hardwareResourceKeyEnvVar: string; let browserResourceKeyEnvVar: string; let noSetHeaderResourceKeyEnvVar: string; - /** - * @deprecated No test reads a licence key under this name. The licence - * key is read from the _51DEGREES_LICENSE_KEY environment variable. - */ let licenseKeyEnvVar: string; } -/** - * @deprecated The name each of envVars replaced. An old name is read only - * when the name that replaced it is unset or empty. Use envVars. - */ export namespace legacyEnvVars { let _51DEGREES_RESOURCE_KEY: string; let _51DEGREES_RESOURCE_KEY_SUPER: string; diff --git a/ip-intelligence/fiftyone.ipintelligence.cloud/types/ipIntelligenceCloudPipelineBuilder.d.ts b/ip-intelligence/fiftyone.ipintelligence.cloud/types/ipIntelligenceCloudPipelineBuilder.d.ts index f592a78f..ea5a8571 100644 --- a/ip-intelligence/fiftyone.ipintelligence.cloud/types/ipIntelligenceCloudPipelineBuilder.d.ts +++ b/ip-intelligence/fiftyone.ipintelligence.cloud/types/ipIntelligenceCloudPipelineBuilder.d.ts @@ -12,15 +12,15 @@ declare class IpIntelligenceCloudPipelineBuilder extends IpIntelligenceCloudPipe * @param {object} options the options for the pipeline builder * @param {string} options.licenceKeys license key(s) used by the * data file update service. A key can be obtained from the - * 51Degrees website: https://51degrees.com/pricing. + * 51Degrees website: https://51degrees.com/pricing?utm_source=code&utm_medium=comment&utm_campaign=51degrees-node&utm_content=fiftyone.ipintelligence.cloud-ipintelligencecloudpipelinebuilder.js&utm_term=constructor. * This parameter MUST be set when using a data file. * If you do not wish to use a key then you can specify * an empty string, but this will cause automatic updates * to be disabled. - * @param {string} options.resourceKey resourceKey * @param {Array|string} options.requestedProperties the fully * qualified names of the properties to ask the cloud service for, such * as ip.registeredcountry. Required with a license key and no resource key. + * @param {string} options.resourceKey resourceKey * @param {number} options.cacheSize size of the default cache * (includes cache if set). * @param {string} options.cloudEndPoint Choose a non default endpoint @@ -30,8 +30,8 @@ declare class IpIntelligenceCloudPipelineBuilder extends IpIntelligenceCloudPipe */ constructor({ licenceKeys, resourceKey, requestedProperties, cacheSize, cloudEndPoint, cloudRequestOrigin }: { licenceKeys: string; - resourceKey: string; requestedProperties: Array | string; + resourceKey: string; cacheSize: number; cloudEndPoint: string; cloudRequestOrigin: string; diff --git a/ip-intelligence/fiftyone.ipintelligence.onpremise/types/ipIntelligenceOnPremise.d.ts b/ip-intelligence/fiftyone.ipintelligence.onpremise/types/ipIntelligenceOnPremise.d.ts index 6d43e791..e2f34eb7 100644 --- a/ip-intelligence/fiftyone.ipintelligence.onpremise/types/ipIntelligenceOnPremise.d.ts +++ b/ip-intelligence/fiftyone.ipintelligence.onpremise/types/ipIntelligenceOnPremise.d.ts @@ -28,7 +28,7 @@ declare class IpIntelligenceOnPremise extends IpIntelligenceOnPremise_base { * will be restricted to * @param {string} options.licenceKeys license key(s) used by the * data file update service. A key can be obtained from the - * 51Degrees website: https://51degrees.com/pricing. + * 51Degrees website: https://51degrees.com/pricing?utm_source=code&utm_medium=comment&utm_campaign=51degrees-node&utm_content=fiftyone.ipintelligence.onpremise-ipintelligenceonpremise.js&utm_term=constructor. * If you do not wish to use a key then you can specify * an empty string, but this will cause automatic updates to * be disabled. @@ -51,7 +51,8 @@ declare class IpIntelligenceOnPremise extends IpIntelligenceOnPremise_base { * @param {string} options.tempDataDir The directory to use for the * temporary data copy if 'createTempDataCopy' is set to true. * @param {boolean} options.updateOnStart whether to download / update - * the datafile on initialisation + * the datafile on initialisation. If there is no file at dataFilePath it + * is downloaded, and processing fails if the download does not work. */ constructor({ dataFilePath, autoUpdate, cache, dataUpdateUrl, dataUpdateVerifyMd5, dataUpdateUseUrlFormatter, restrictedProperties, licenceKeys, download, performanceProfile, reuseTempFile, concurrency, fileSystemWatcher, pollingInterval, updateTimeMaximumRandomisation, createTempDataCopy, tempDataDir, updateOnStart }: { dataFilePath: string; diff --git a/ip-intelligence/fiftyone.ipintelligence.onpremise/types/ipIntelligenceOnPremisePipelineBuilder.d.ts b/ip-intelligence/fiftyone.ipintelligence.onpremise/types/ipIntelligenceOnPremisePipelineBuilder.d.ts index ec6bf9fa..b84322fd 100644 --- a/ip-intelligence/fiftyone.ipintelligence.onpremise/types/ipIntelligenceOnPremisePipelineBuilder.d.ts +++ b/ip-intelligence/fiftyone.ipintelligence.onpremise/types/ipIntelligenceOnPremisePipelineBuilder.d.ts @@ -12,7 +12,7 @@ declare class IpIntelligenceOnPremisePipelineBuilder extends IpIntelligenceOnPre * @param {object} options the options for the pipeline builder * @param {string} [options.licenceKeys] license key(s) used by the * data file update service. A key can be obtained from the - * 51Degrees website: https://51degrees.com/pricing. + * 51Degrees website: https://51degrees.com/pricing?utm_source=code&utm_medium=comment&utm_campaign=51degrees-node&utm_content=fiftyone.ipintelligence.onpremise-ipintelligenceonpremisepipelinebuilder.js&utm_term=constructor. * This parameter MUST be set when using a data file. * If you do not wish to use a key then you can specify * an empty string, but this will cause automatic updates diff --git a/ip-intelligence/fiftyone.ipintelligence.shared/types/index.d.ts b/ip-intelligence/fiftyone.ipintelligence.shared/types/index.d.ts index d29799b0..5597866b 100644 --- a/ip-intelligence/fiftyone.ipintelligence.shared/types/index.d.ts +++ b/ip-intelligence/fiftyone.ipintelligence.shared/types/index.d.ts @@ -17,21 +17,8 @@ export let errorMessages: { export let testConstants: { envVars: { superResourceKeyVariable: string; - /** - * @deprecated The name the variable had before, which is read only - * when the variable superResourceKeyVariable names is unset or empty. - * Use superResourceKeyVariable. - */ superResourceKeyEnvVar: string; - /** - * @deprecated No test reads a resource key under this name. Use - * superResourceKeyVariable. - */ ipiResourceKeyEnvVar: string; - /** - * @deprecated No test reads a licence key under this name. The licence - * key is read from the _51DEGREES_LICENSE_KEY environment variable. - */ licenseKeyEnvVar: string; }; ipAddresses: { diff --git a/ip-intelligence/fiftyone.ipintelligence.shared/types/lib/testConstants.d.ts b/ip-intelligence/fiftyone.ipintelligence.shared/types/lib/testConstants.d.ts index 21ce6616..a0b037af 100644 --- a/ip-intelligence/fiftyone.ipintelligence.shared/types/lib/testConstants.d.ts +++ b/ip-intelligence/fiftyone.ipintelligence.shared/types/lib/testConstants.d.ts @@ -1,20 +1,7 @@ export namespace envVars { let superResourceKeyVariable: string; - /** - * @deprecated The name the variable had before, which is read only - * when the variable superResourceKeyVariable names is unset or empty. - * Use superResourceKeyVariable. - */ let superResourceKeyEnvVar: string; - /** - * @deprecated No test reads a resource key under this name. Use - * superResourceKeyVariable. - */ let ipiResourceKeyEnvVar: string; - /** - * @deprecated No test reads a licence key under this name. The licence - * key is read from the _51DEGREES_LICENSE_KEY environment variable. - */ let licenseKeyEnvVar: string; } export namespace ipAddresses { diff --git a/location/types/geoLocationCloud.d.ts b/location/types/geoLocationCloud.d.ts index 3fcd7378..8cc411d4 100644 --- a/location/types/geoLocationCloud.d.ts +++ b/location/types/geoLocationCloud.d.ts @@ -1,5 +1,6 @@ export = GeoLocationCloud; -declare class GeoLocationCloud { +declare const GeoLocationCloud_base: typeof import("fiftyone.pipeline.cloudrequestengine/types/cloudEngine"); +declare class GeoLocationCloud extends GeoLocationCloud_base { /** * Constructor for GeoLocationCloud * @@ -9,5 +10,4 @@ declare class GeoLocationCloud { constructor({ locationProvider }: { locationProvider: string; }, ...args: any[]); - dataKey: string; } diff --git a/pipeline/fiftyone.pipeline.cloudrequestengine/types/cloudHelpers.d.ts b/pipeline/fiftyone.pipeline.cloudrequestengine/types/cloudHelpers.d.ts deleted file mode 100644 index 56a89eb7..00000000 --- a/pipeline/fiftyone.pipeline.cloudrequestengine/types/cloudHelpers.d.ts +++ /dev/null @@ -1 +0,0 @@ -export function makeHTTPRequest(url: string): Promise; diff --git a/pipeline/fiftyone.pipeline.cloudrequestengine/types/cloudRequestEngine.d.ts b/pipeline/fiftyone.pipeline.cloudrequestengine/types/cloudRequestEngine.d.ts index 801f4acd..c4438a54 100644 --- a/pipeline/fiftyone.pipeline.cloudrequestengine/types/cloudRequestEngine.d.ts +++ b/pipeline/fiftyone.pipeline.cloudrequestengine/types/cloudRequestEngine.d.ts @@ -1,9 +1,5 @@ export = CloudRequestEngine; declare const CloudRequestEngine_base: typeof import("fiftyone.pipeline.engines/types/engine"); -/** - * @typedef {import('fiftyone.pipeline.core').FlowData} FlowData - * @typedef {import('fiftyone.pipeline.core').Evidence} Evidence - */ declare class CloudRequestEngine extends CloudRequestEngine_base { /** * Constructor for CloudRequestEngine @@ -86,17 +82,7 @@ declare class CloudRequestEngine extends CloudRequestEngine_base { * @returns {Promise} resolved once the FlowData is processed */ process(flowData: FlowData): Promise; - discovery: Promise; - /** - * A response with a top level `fodid` member, in any case, holds a 51Did - * created for the one request, so it is neither stored in the cache nor - * served from it. The answer is worked out once for each element data, - * so a cache hit does not parse the response again. - * - * @param {object} data the element data of a response - * @returns {boolean} false if the response has a top level fodid member - */ - isCacheable(data: object): boolean; + discovery: any; /** * Typically, cloud will return errors as JSON. * However, transport level errors or other failures can result in @@ -219,7 +205,8 @@ declare class CloudRequestEngine extends CloudRequestEngine_base { */ getSelectedEvidence(evidence: Evidence, type: string): Evidence; /** - * Check that the key of a KeyValuePair has the given prefix. + * Check that the key of a KeyValuePair has the given prefix, ignoring + * letter case as evidence keys do. * * @param {string} itemKey Key to check * @param {string} prefix The prefix to check for. diff --git a/pipeline/fiftyone.pipeline.core/types/callbackUrl.d.ts b/pipeline/fiftyone.pipeline.core/types/callbackUrl.d.ts new file mode 100644 index 00000000..790c0572 --- /dev/null +++ b/pipeline/fiftyone.pipeline.core/types/callbackUrl.d.ts @@ -0,0 +1,32 @@ +export = callbackUrl; +/** + * Builds the callback URL from its parts and checks it. One slash separates + * the host and the endpoint, being added when neither has one and removed + * when both do. The protocol and the host are written in lower case and the + * rest as given, apart from the percent-encoding. The host value holds no + * '?', '#' or '@'. + * + * @param {*} protocol the protocol, http or https in any case + * @param {*} host the host, which can end with a port and a path + * @param {*} endPoint the endpoint + * @returns {{valid: boolean, url: string}|null} null when the protocol, + * host or endpoint is not set. Otherwise whether the URL is valid, and the + * URL to write into the script when it is, or the URL as it was built, for + * the log, when it is not. The logged URL shows '***' in place of everything + * in the host before its last '@'. + */ +declare function callbackUrl(protocol: any, host: any, endPoint: any): { + valid: boolean; + url: string; +} | null; +declare namespace callbackUrl { + export { isScheme }; +} +/** + * Whether the protocol is http or https, ignoring the case of its ASCII + * letters only. + * + * @param {string} protocol the protocol + * @returns {boolean} true if the protocol is http or https + */ +declare function isScheme(protocol: string): boolean; diff --git a/pipeline/fiftyone.pipeline.core/types/elementDataDictionary.d.ts b/pipeline/fiftyone.pipeline.core/types/elementDataDictionary.d.ts index 43c68d84..fbfba8b5 100644 --- a/pipeline/fiftyone.pipeline.core/types/elementDataDictionary.d.ts +++ b/pipeline/fiftyone.pipeline.core/types/elementDataDictionary.d.ts @@ -26,15 +26,6 @@ declare class ElementDataDictionary extends ElementData { * @returns {number} integer value */ getInternal(key: string): number; - /** - * Looks for a key in the dictionary ignoring its letter case. The contents - * can change after the data is made, so they are searched each time - * rather than indexed once. - * - * @param {string} key the property key to retrieve - * @returns {*} the value, or undefined if there is none - */ - getInternalIgnoringCase(key: string): any; [Symbol.iterator](): Generator; } declare namespace ElementDataDictionary { diff --git a/pipeline/fiftyone.pipeline.core/types/evidence.d.ts b/pipeline/fiftyone.pipeline.core/types/evidence.d.ts index a79f9470..b7fb2694 100644 --- a/pipeline/fiftyone.pipeline.core/types/evidence.d.ts +++ b/pipeline/fiftyone.pipeline.core/types/evidence.d.ts @@ -14,7 +14,7 @@ declare class Evidence { constructor(flowData: FlowData); flowData: import("./flowData"); evidenceStore: {}; - keys: {}; + keys: any; unacceptedStore: {}; /** * The web request as server.http-request holds it, being every value diff --git a/pipeline/fiftyone.pipeline.core/types/flowElement.d.ts b/pipeline/fiftyone.pipeline.core/types/flowElement.d.ts index fddfa94c..51941aa6 100644 --- a/pipeline/fiftyone.pipeline.core/types/flowElement.d.ts +++ b/pipeline/fiftyone.pipeline.core/types/flowElement.d.ts @@ -20,8 +20,10 @@ declare class FlowElement { * elementData will be stored under * @param {Function} options.processInternal callback to act on flowData * @param {object} options.properties list of properties including metadata - * @param {EvidenceKeyFilter} options.evidenceKeyFilter an instance of - * an EvidenceKeyFilter to filter evidence added to the Pipeline + * @param {EvidenceKeyFilter} options.evidenceKeyFilter the evidence the + * element accepts, being the keys that can change its results. An element + * that gives none accepts no evidence, so it never widens what the + * Pipeline keeps * @param {EvidenceKeyFilter} [options.keptEvidenceKeyFilter] the evidence * the element reads without it changing its results, which the flow data * keeps but which is not accepted evidence @@ -44,7 +46,7 @@ declare class FlowElement { */ processInternal(flowData: FlowData): any; properties: object; - evidenceKeyFilter: EvidenceKeyFilterBase; + evidenceKeyFilter: import("./evidenceKeyFilter"); /** * Evidence the flow data keeps for the element, though it is not * accepted, such as the evidence the usage sharing element shares. @@ -111,7 +113,6 @@ declare class FlowElement { declare namespace FlowElement { export { FlowData, Pipeline, EvidenceKeyFilter }; } -import EvidenceKeyFilterBase = require("./evidenceKeyFilter"); type FlowData = import("./flowData"); type Pipeline = import("./pipeline"); type EvidenceKeyFilter = import("./evidenceKeyFilter"); diff --git a/pipeline/fiftyone.pipeline.core/types/javascriptbuilder.d.ts b/pipeline/fiftyone.pipeline.core/types/javascriptbuilder.d.ts index 0bf9ea8d..6dec7f80 100644 --- a/pipeline/fiftyone.pipeline.core/types/javascriptbuilder.d.ts +++ b/pipeline/fiftyone.pipeline.core/types/javascriptbuilder.d.ts @@ -18,10 +18,14 @@ declare class JavaScriptBuilderElement extends FlowElement { * * @param {object} options options object * @param {string} options.objName the name of the client - * side object with the JavaScript properties in it - * @param {string} options.protocol The protocol ("http" or "https") - * used by the client side callback url. - * This can be overriden with header.protocol evidence + * side object with the JavaScript properties in it. This must be a valid + * JavaScript identifier that is not a reserved word, or the constructor + * throws. Leaving it out, or giving null, means "fod". This can be overridden with "query.fod-js-object-name" evidence, + * which is ignored with a warning when it is not a valid name. + * @param {string} options.protocol The protocol of the client side + * callback url, http or https in any case of its ASCII letters. The + * constructor throws for any other protocol. Left out, the header.protocol + * evidence is used, or https when there is none * @param {string} options.host The host of the client side * callback url. This can be overriden with header.host evidence. * @param {string} options.endPoint The endpoint of the client side @@ -29,7 +33,7 @@ declare class JavaScriptBuilderElement extends FlowElement { * @param {boolean} options.enableCookies Whether the client JavaScript * stored results of client side processing in cookies. This can also * be set per request, using the "query.fod-js-enable-cookies" evidence key. - * For more details on personal data policy, see http://51degrees.com/terms/client-services-privacy-policy/ + * For more details on personal data policy, see https://51degrees.com/terms/client-services-privacy-policy/?utm_source=code&utm_medium=comment&utm_campaign=51degrees-node&utm_content=fiftyone.pipeline.core-javascriptbuilder.js&utm_term=constructor * @param {boolean} options.minify Whether to minify the JavaScript */ constructor({ objName, protocol, host, endPoint, enableCookies, minify }?: { @@ -49,6 +53,7 @@ declare class JavaScriptBuilderElement extends FlowElement { minify: boolean; }; evidenceKeyFilter: JSEvidenceKeyFilter; + _invalidUrlLogged: boolean; /** * Internal process function of the JavaScript builder * Gets JSON from the JSONBundler and constructs JavaScript @@ -67,11 +72,9 @@ import FlowElement = require("./flowElement.js"); * @typedef {import('./flowData')} FlowData */ /** - * The evidence the JavaScript builder reads, being every query value, which - * the script sends back as its parameters, and the host and protocol of the - * callback URL. Other headers do not change the script, so they are not - * accepted. - **/ + * The script reads the query string, and the host and protocol it calls + * back to, so those are the evidence that can change it. + */ declare class JSEvidenceKeyFilter extends EvidenceKeyFilter { filterEvidenceKey(key: any): boolean; } diff --git a/pipeline/fiftyone.pipeline.core/types/jsonbundler.d.ts b/pipeline/fiftyone.pipeline.core/types/jsonbundler.d.ts index 92854141..c2ec6de5 100644 --- a/pipeline/fiftyone.pipeline.core/types/jsonbundler.d.ts +++ b/pipeline/fiftyone.pipeline.core/types/jsonbundler.d.ts @@ -12,6 +12,15 @@ declare class JSONBundlerElement extends FlowElement { constructor(...args: any[]); evidenceKeyFilter: BasicListEvidenceKeyFilter; propertyCache: {}; + /** + * The sequence number the Sequence Element produced, which is its Element + * Data or, as a whole number a caller put in the evidence, query.sequence. + * Text from a query string does not count. + * + * @param {FlowData} flowData the FlowData being processed + * @returns {number} the sequence number + */ + getSequence(flowData: FlowData): number; /** * The JSON Builder extracts all properties and serializes them into JSON * diff --git a/pipeline/fiftyone.pipeline.core/types/pipeline.d.ts b/pipeline/fiftyone.pipeline.core/types/pipeline.d.ts index 286ae7c9..d06c0be3 100644 --- a/pipeline/fiftyone.pipeline.core/types/pipeline.d.ts +++ b/pipeline/fiftyone.pipeline.core/types/pipeline.d.ts @@ -1,7 +1,7 @@ export = Pipeline; /** * @typedef {import('./flowElement')} FlowElement - * @typedef {import('fiftyone.pipeline.engines').DataFileUpdateService} DataFileUpdateService + * @typedef {any} DataFileUpdateService */ /** * Pipeline holding a list of flowElements for processing, can create diff --git a/pipeline/fiftyone.pipeline.core/types/pipelineBuilder.d.ts b/pipeline/fiftyone.pipeline.core/types/pipelineBuilder.d.ts index 9a3a1ba3..987e99aa 100644 --- a/pipeline/fiftyone.pipeline.core/types/pipelineBuilder.d.ts +++ b/pipeline/fiftyone.pipeline.core/types/pipelineBuilder.d.ts @@ -62,6 +62,10 @@ declare class PipelineBuilder { flowElements: FlowElement[]; dataFileUpdateService: any; addJavaScriptBuilder: boolean; + addSequenceElement: boolean; + addJsonBuilderElement: boolean; + addJavaScriptBuilderElement: boolean; + addSetHeadersElement: boolean; javascriptBuilderSettings: { objName: string; protocol: string; @@ -70,11 +74,7 @@ declare class PipelineBuilder { enableCookies: boolean; minify: boolean; }; - addSequenceElement: boolean; - addJsonBuilderElement: boolean; - addJavaScriptBuilderElement: boolean; useSetHeaderProperties: boolean; - addSetHeadersElement: boolean; suppressProcessExceptions: boolean; /** * Helper that loads a JSON configuration file from @@ -103,7 +103,12 @@ declare class PipelineBuilder { */ getSuppressProcessExceptions(config: object): boolean; /** - * Add required elements to an existing FlowElement array + * Add required elements to an existing FlowElement array. Each web + * integration element is added only where the array has no element with + * its key, compared ignoring case, so one the caller added is the one + * used and building twice adds nothing more. A JSON Builder goes + * immediately before a JavaScript Builder the caller added, which reads + * what it writes. * * @param {FlowElement[]} flowElements array of elements to add to * @returns {FlowElement[]} resulting array with required elements diff --git a/pipeline/fiftyone.pipeline.engines/types/aspectDataDictionary.d.ts b/pipeline/fiftyone.pipeline.engines/types/aspectDataDictionary.d.ts index 07cfc583..5fb1f300 100644 --- a/pipeline/fiftyone.pipeline.engines/types/aspectDataDictionary.d.ts +++ b/pipeline/fiftyone.pipeline.engines/types/aspectDataDictionary.d.ts @@ -32,14 +32,6 @@ declare class AspectDataDictionary extends AspectData { * @returns {*} property value */ getInternal(key: string): any; - /** - * Looks for a key in the dictionary ignoring its letter case, as the core - * dictionary does. - * - * @param {string} key property key - * @returns {*} property value, or undefined if there is none - */ - getInternalIgnoringCase(key: string): any; [Symbol.iterator](): Generator; } declare namespace AspectDataDictionary { diff --git a/pipeline/fiftyone.pipeline.engines/types/dataFile.d.ts b/pipeline/fiftyone.pipeline.engines/types/dataFile.d.ts index 1be37b83..95292d78 100644 --- a/pipeline/fiftyone.pipeline.engines/types/dataFile.d.ts +++ b/pipeline/fiftyone.pipeline.engines/types/dataFile.d.ts @@ -110,6 +110,7 @@ declare class DataFile { * @param {string} identifier the identifier of the datafile */ refresh(identifier: string): void; + onUpdateComplete: Function; updating: boolean; /** * Getter for the update url for the datafile update service to use diff --git a/pipeline/fiftyone.pipeline.engines/types/dataFileUpdateService.d.ts b/pipeline/fiftyone.pipeline.engines/types/dataFileUpdateService.d.ts index 1d808cb6..fc55b206 100644 --- a/pipeline/fiftyone.pipeline.engines/types/dataFileUpdateService.d.ts +++ b/pipeline/fiftyone.pipeline.engines/types/dataFileUpdateService.d.ts @@ -41,19 +41,14 @@ declare class DataFileUpdateService { * @param {Function} callback callback */ once(listener: string | symbol, callback: Function): void; - /** - * Method that updates a datafile when it is due an update - * - * @param {DataFile} dataFile the datafile to update - * @param {boolean} [automatic] true where the update is one the service - * started itself, on start-up or when the polling interval has passed, - * and not one an application asked for. Only the log messages differ. - * @returns {boolean | void} returns false if already updating - * or request failed - */ - updateDataFile(dataFile: DataFile, automatic?: boolean): boolean | void; /** * Writes a message to the log of the pipeline the service is attached to. + * With no pipeline, an error is written to the console, as a pipeline + * with no error listener does, so that it is not lost. + * + * The service's messages name the update URL, which carries the license + * keys, so every one of them is masked here. The pipeline's log does not + * mask, because each detection goes through it. * * @param {string} level the log level * @param {*} message the message @@ -61,24 +56,65 @@ declare class DataFileUpdateService { log(level: string, message: any): void; /** * Reports how an update ended, to the listeners of 'updateComplete' and - * to the data file's own onUpdateComplete function, if it has one. + * to the data file's own onUpdateComplete function, if it has one. An + * error thrown by any of them is logged, goes no further, and the + * callbacks after it are not called. * * @param {DataFile} dataFile the data file the update was for * @param {string} status one of the AutoUpdateStatus values */ complete(dataFile: DataFile, status: string): void; /** - * Refreshes a data file that is held in memory with the bytes given. The - * data file keeps the data it has if the refresh fails. Nothing is - * downloaded and no file is written. + * The message for a data update service that could not be reached. * - * @param {DataFile} dataFile the memory data file to refresh - * @param {Buffer | Uint8Array} buffer the new data - * @returns {boolean} false if the data file is already updating or the - * refresh failed, which is also logged and reported through the - * 'updateComplete' event + * @param {DataFile} dataFile the data file being updated + * @returns {string} the message to log */ - updateFromMemory(dataFile: DataFile, buffer: Buffer | Uint8Array): boolean; + accessError(dataFile: DataFile): string; + /** + * Refreshes the engine of a data file with the data now in place, and + * logs a failure. The caller reports the outcome. + * + * @param {DataFile} dataFile the data file to refresh + * @param {boolean} [fromFile] true where the data came from a file that + * was written, which is the case the message names a try count for + * @returns {boolean} true if the refresh worked + */ + refreshDataFile(dataFile: DataFile, fromFile?: boolean): boolean; + /** + * Ends an update that failed, so that the next one can be scheduled. + * + * @param {DataFile} dataFile the data file being updated + * @param {string} status the AutoUpdateStatus to report + */ + fail(dataFile: DataFile, status: string): void; + /** + * Method that updates a datafile when it is due an update + * + * @param {DataFile} dataFile the datafile to update + * @param {boolean} [automatic] true where the update is one the service + * started itself, on start-up or when the polling interval has passed, + * and not one an application asked for. Only the log messages differ. + * @returns {boolean | void} returns false if already updating + * or request failed + */ + updateDataFile(dataFile: DataFile, automatic?: boolean): boolean | void; + /** + * Logs an error that has no message of its own, with its cause. + * + * @param {DataFile} dataFile the data file being updated + * @param {*} error the error, or whatever was thrown + */ + unhandled(dataFile: DataFile, error: any): void; + /** + * Logs a download whose MD5 hash does not match the one the response + * carried. + * + * @param {DataFile} dataFile the data file being updated + * @param {string} serverHash the hash the response carried + * @param {string} downloadHash the hash of the data that arrived + */ + integrityFailed(dataFile: DataFile, serverHash: string, downloadHash: string): void; /** * Internal method called when the datafile has * been downloaded and is ready after an update @@ -96,6 +132,18 @@ declare class DataFileUpdateService { * @param {string} filename the filename of the downloaded data */ processFile(dataFile: DataFile, filename: string): void; + /** + * Refreshes a data file that is held in memory with the bytes given. The + * data file keeps the data it has if the refresh fails. Nothing is + * downloaded and no file is written. + * + * @param {DataFile} dataFile the memory data file to refresh + * @param {Buffer | Uint8Array} buffer the new data + * @returns {boolean} false if the data file is already updating or the + * refresh failed, which is also logged and reported through the + * 'updateComplete' event + */ + updateFromMemory(dataFile: DataFile, buffer: Buffer | Uint8Array): boolean; /** * Internal method to check the next update of a * datafile at a polling interval set on the datafile diff --git a/pipeline/fiftyone.pipeline.engines/types/engine.d.ts b/pipeline/fiftyone.pipeline.engines/types/engine.d.ts index 07ce8bff..c7ef4295 100644 --- a/pipeline/fiftyone.pipeline.engines/types/engine.d.ts +++ b/pipeline/fiftyone.pipeline.engines/types/engine.d.ts @@ -36,23 +36,24 @@ declare class Engine extends Engine_base { * @type {Set} */ restrictedPropertyKeys: Set; - /** - * Checks cache and returns cached result if found. - * - * @param {FlowData} flowData checks if a FlowData's evidence - * is already in the cache and processing can be bypassed - * @returns {boolean} whether in cache - */ - inCache(flowData: FlowData): boolean; /** * Whether a result may be stored in the cache and served from it. A result * that holds a value created for the one request that asked for it, such - * as a 51Did, must not be. + * as a 51Did, must not be, or the next request with the same evidence + * would be given it. * * @param {object} data the element data of a result * @returns {boolean} true unless the result holds such a value */ isCacheable(data: object): boolean; + /** + * Checks cache and returns cached result if found. + * + * @param {FlowData} flowData checks if a FlowData's evidence + * is already in the cache and processing can be bypassed + * @returns {boolean} whether in cache + */ + inCache(flowData: FlowData): boolean; /** * An engine's process function checks cache for an item * (calling inCache) diff --git a/pipeline/fiftyone.pipeline.engines/types/index.d.ts b/pipeline/fiftyone.pipeline.engines/types/index.d.ts index d2e54e61..65e49c0d 100644 --- a/pipeline/fiftyone.pipeline.engines/types/index.d.ts +++ b/pipeline/fiftyone.pipeline.engines/types/index.d.ts @@ -19,5 +19,7 @@ export let AutoUpdateStatus: { AUTO_UPDATE_ERR_MD5_VALIDATION_FAILED: string; AUTO_UPDATE_NEW_FILE_CANT_RENAME: string; AUTO_UPDATE_REFRESH_FAILED: string; + AUTO_UPDATE_TEMP_PATH_NOT_SET: string; + AUTO_UPDATE_UNKNOWN_ERROR: string; }; export let Tracker: typeof import("./tracker");