crawlee-one 1.0.0

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.
Files changed (131) hide show
  1. package/README.md +81 -0
  2. package/dist/cjs/cli/cli.d.ts +1 -0
  3. package/dist/cjs/cli/cli.js +61 -0
  4. package/dist/cjs/cli/cli.js.map +1 -0
  5. package/dist/cjs/cli/index.d.ts +2 -0
  6. package/dist/cjs/cli/index.js +6 -0
  7. package/dist/cjs/cli/index.js.map +1 -0
  8. package/dist/cjs/index.d.ts +24 -0
  9. package/dist/cjs/index.js +43 -0
  10. package/dist/cjs/index.js.map +1 -0
  11. package/dist/cjs/lib/actions/dom.d.ts +102 -0
  12. package/dist/cjs/lib/actions/dom.js +743 -0
  13. package/dist/cjs/lib/actions/dom.js.map +1 -0
  14. package/dist/cjs/lib/actions/domUtils.d.ts +42 -0
  15. package/dist/cjs/lib/actions/domUtils.js +126 -0
  16. package/dist/cjs/lib/actions/domUtils.js.map +1 -0
  17. package/dist/cjs/lib/actions/page.d.ts +69 -0
  18. package/dist/cjs/lib/actions/page.js +205 -0
  19. package/dist/cjs/lib/actions/page.js.map +1 -0
  20. package/dist/cjs/lib/actions/scrapeListing.d.ts +78 -0
  21. package/dist/cjs/lib/actions/scrapeListing.js +242 -0
  22. package/dist/cjs/lib/actions/scrapeListing.js.map +1 -0
  23. package/dist/cjs/lib/actor/actor.d.ts +90 -0
  24. package/dist/cjs/lib/actor/actor.js +306 -0
  25. package/dist/cjs/lib/actor/actor.js.map +1 -0
  26. package/dist/cjs/lib/actor/types.d.ts +162 -0
  27. package/dist/cjs/lib/actor/types.js +3 -0
  28. package/dist/cjs/lib/actor/types.js.map +1 -0
  29. package/dist/cjs/lib/actor.d.ts +189 -0
  30. package/dist/cjs/lib/actor.js +225 -0
  31. package/dist/cjs/lib/actor.js.map +1 -0
  32. package/dist/cjs/lib/actorSpec.d.ts +20 -0
  33. package/dist/cjs/lib/actorSpec.js +3 -0
  34. package/dist/cjs/lib/actorSpec.js.map +1 -0
  35. package/dist/cjs/lib/config.d.ts +561 -0
  36. package/dist/cjs/lib/config.js +707 -0
  37. package/dist/cjs/lib/config.js.map +1 -0
  38. package/dist/cjs/lib/dataset/maxCount.d.ts +30 -0
  39. package/dist/cjs/lib/dataset/maxCount.js +55 -0
  40. package/dist/cjs/lib/dataset/maxCount.js.map +1 -0
  41. package/dist/cjs/lib/dataset/pushData.d.ts +123 -0
  42. package/dist/cjs/lib/dataset/pushData.js +182 -0
  43. package/dist/cjs/lib/dataset/pushData.js.map +1 -0
  44. package/dist/cjs/lib/dataset.d.ts +98 -0
  45. package/dist/cjs/lib/dataset.js +122 -0
  46. package/dist/cjs/lib/dataset.js.map +1 -0
  47. package/dist/cjs/lib/dom.d.ts +78 -0
  48. package/dist/cjs/lib/dom.js +243 -0
  49. package/dist/cjs/lib/dom.js.map +1 -0
  50. package/dist/cjs/lib/error/errorHandler.d.ts +112 -0
  51. package/dist/cjs/lib/error/errorHandler.js +164 -0
  52. package/dist/cjs/lib/error/errorHandler.js.map +1 -0
  53. package/dist/cjs/lib/error/sentry.d.ts +11 -0
  54. package/dist/cjs/lib/error/sentry.js +60 -0
  55. package/dist/cjs/lib/error/sentry.js.map +1 -0
  56. package/dist/cjs/lib/integrations/apify.d.ts +67 -0
  57. package/dist/cjs/lib/integrations/apify.js +106 -0
  58. package/dist/cjs/lib/integrations/apify.js.map +1 -0
  59. package/dist/cjs/lib/integrations/types.d.ts +274 -0
  60. package/dist/cjs/lib/integrations/types.js +3 -0
  61. package/dist/cjs/lib/integrations/types.js.map +1 -0
  62. package/dist/cjs/lib/io/dataset.d.ts +67 -0
  63. package/dist/cjs/lib/io/dataset.js +86 -0
  64. package/dist/cjs/lib/io/dataset.js.map +1 -0
  65. package/dist/cjs/lib/io/maxCount.d.ts +30 -0
  66. package/dist/cjs/lib/io/maxCount.js +55 -0
  67. package/dist/cjs/lib/io/maxCount.js.map +1 -0
  68. package/dist/cjs/lib/io/pushData.d.ts +124 -0
  69. package/dist/cjs/lib/io/pushData.js +193 -0
  70. package/dist/cjs/lib/io/pushData.js.map +1 -0
  71. package/dist/cjs/lib/io/pushRequests.d.ts +38 -0
  72. package/dist/cjs/lib/io/pushRequests.js +63 -0
  73. package/dist/cjs/lib/io/pushRequests.js.map +1 -0
  74. package/dist/cjs/lib/io/requestQueue.d.ts +28 -0
  75. package/dist/cjs/lib/io/requestQueue.js +40 -0
  76. package/dist/cjs/lib/io/requestQueue.js.map +1 -0
  77. package/dist/cjs/lib/log.d.ts +38 -0
  78. package/dist/cjs/lib/log.js +54 -0
  79. package/dist/cjs/lib/log.js.map +1 -0
  80. package/dist/cjs/lib/migrate/localMigrator.d.ts +10 -0
  81. package/dist/cjs/lib/migrate/localMigrator.js +57 -0
  82. package/dist/cjs/lib/migrate/localMigrator.js.map +1 -0
  83. package/dist/cjs/lib/migrate/localState.d.ts +7 -0
  84. package/dist/cjs/lib/migrate/localState.js +43 -0
  85. package/dist/cjs/lib/migrate/localState.js.map +1 -0
  86. package/dist/cjs/lib/migrate/types.d.ts +6 -0
  87. package/dist/cjs/lib/migrate/types.js +3 -0
  88. package/dist/cjs/lib/migrate/types.js.map +1 -0
  89. package/dist/cjs/lib/readme/readme.d.ts +65 -0
  90. package/dist/cjs/lib/readme/readme.js +534 -0
  91. package/dist/cjs/lib/readme/readme.js.map +1 -0
  92. package/dist/cjs/lib/readme/types.d.ts +260 -0
  93. package/dist/cjs/lib/readme/types.js +54 -0
  94. package/dist/cjs/lib/readme/types.js.map +1 -0
  95. package/dist/cjs/lib/router.d.ts +132 -0
  96. package/dist/cjs/lib/router.js +165 -0
  97. package/dist/cjs/lib/router.js.map +1 -0
  98. package/dist/cjs/lib/scraper/scrapeListing.d.ts +78 -0
  99. package/dist/cjs/lib/scraper/scrapeListing.js +242 -0
  100. package/dist/cjs/lib/scraper/scrapeListing.js.map +1 -0
  101. package/dist/cjs/lib/test/actor.d.ts +21 -0
  102. package/dist/cjs/lib/test/actor.js +56 -0
  103. package/dist/cjs/lib/test/actor.js.map +1 -0
  104. package/dist/cjs/lib/test/mockApifyClient.d.ts +32 -0
  105. package/dist/cjs/lib/test/mockApifyClient.js +176 -0
  106. package/dist/cjs/lib/test/mockApifyClient.js.map +1 -0
  107. package/dist/cjs/types.d.ts +31 -0
  108. package/dist/cjs/types.js +3 -0
  109. package/dist/cjs/types.js.map +1 -0
  110. package/dist/cjs/utils/async.d.ts +19 -0
  111. package/dist/cjs/utils/async.js +74 -0
  112. package/dist/cjs/utils/async.js.map +1 -0
  113. package/dist/cjs/utils/error.d.ts +1 -0
  114. package/dist/cjs/utils/error.js +10 -0
  115. package/dist/cjs/utils/error.js.map +1 -0
  116. package/dist/cjs/utils/format.d.ts +9 -0
  117. package/dist/cjs/utils/format.js +19 -0
  118. package/dist/cjs/utils/format.js.map +1 -0
  119. package/dist/cjs/utils/package.d.ts +15 -0
  120. package/dist/cjs/utils/package.js +25 -0
  121. package/dist/cjs/utils/package.js.map +1 -0
  122. package/dist/cjs/utils/types.d.ts +6 -0
  123. package/dist/cjs/utils/types.js +9 -0
  124. package/dist/cjs/utils/types.js.map +1 -0
  125. package/dist/cjs/utils/url.d.ts +9 -0
  126. package/dist/cjs/utils/url.js +32 -0
  127. package/dist/cjs/utils/url.js.map +1 -0
  128. package/dist/cjs/utils/valueMonitor.d.ts +31 -0
  129. package/dist/cjs/utils/valueMonitor.js +91 -0
  130. package/dist/cjs/utils/valueMonitor.js.map +1 -0
  131. package/package.json +85 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/lib/config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Actor } from 'apify';\nimport type { CheerioCrawlerOptions } from 'crawlee';\nimport {\n createBooleanField,\n createIntegerField,\n createObjectField,\n createStringField,\n createArrayField,\n Field,\n} from 'apify-actor-config';\nimport Joi from 'joi';\n\nimport type { CrawlerUrl } from '../types';\nimport { LOG_LEVEL, LogLevel } from './log';\n\nexport type AllActorInputs = InputActorInput &\n CrawlerConfigActorInput &\n PerfActorInput &\n StartUrlsActorInput &\n LoggingActorInput &\n ProxyActorInput &\n PrivacyActorInput &\n RequestActorInput &\n OutputActorInput &\n MetamorphActorInput;\n\n/** Crawler config fields that can be overriden from the actor input */\nexport type CrawlerConfigActorInput = Pick<\n CheerioCrawlerOptions,\n | 'navigationTimeoutSecs'\n | 'ignoreSslErrors'\n | 'additionalMimeTypes'\n | 'suggestResponseEncoding'\n | 'forceResponseEncoding'\n | 'requestHandlerTimeoutSecs'\n | 'maxRequestRetries'\n | 'maxRequestsPerCrawl'\n | 'maxRequestsPerMinute'\n | 'minConcurrency'\n | 'maxConcurrency'\n | 'keepAlive'\n>;\n\n/** Common input fields related to extending Actor input with remote or generated data */\nexport interface InputActorInput {\n /**\n * If set, the Actor input is extended with a config from this URL.\n *\n * For example, you can store your actor input in a source control, and import it here.\n *\n * In case of a conflict (if a field is defined both in Actor input and in imported input)\n * the Actor input overwrites the imported fields.\n *\n * The URL must point to a JSON file containing a single object (the config).\n */\n inputExtendUrl?: string;\n /**\n * If set, the Actor input is extended with a config from this custom function.\n *\n * For example, you can store your actor input in a source control, and import it here.\n *\n * In case of a conflict (if a field is defined both in Actor input and in imported input)\n * the Actor input overwrites the imported fields.\n *\n * The URL must point to a JSON file containing a single object (the config).\n */\n inputExtendFromFunction?: string;\n}\n\n/** Common input fields related to performance which are not part of the CrawlerConfig */\nexport interface PerfActorInput {\n /**\n * If set, multiple Requests will be handled by a single Actor instance.\n *\n * See official docs: https://docs.apify.com/platform/actors/development/performance#batch-jobs-win-over-the-single-jobs\n *\n * Example: If set to 20, then up to 20 requests will be handled in a single \"go\".\n */\n perfBatchSize?: number;\n /**\n * How long to wait between entries within a single batch.\n *\n * Increase this value if you're using batching and you're sending requests to the scraped website too fast.\n *\n * Example: If set to 1, then after each entry in a batch, wait 1 second before continuing.\n */\n perfBatchWaitSecs?: number;\n}\n\n/** Common input fields for defining URLs to scrape */\nexport interface StartUrlsActorInput {\n /** URLs to start with, defined manually as a list of strings or crawler requests */\n startUrls?: CrawlerUrl[];\n /**\n * Import starting URLs from an existing Dataset.\n *\n * String is in the format `datasetID#field` (e.g. `datasetid123#url`).\n */\n startUrlsFromDataset?: string;\n /**\n * Import or generate starting URLs using a custom function.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * ```js\n * // Example: Create and load URLs from a Dataset by combining multiple fields\n * async ({ io, input, state, itemCacheKey }) => {\n * const dataset = await io.openDataset(datasetNameOrId);\n * const data = await dataset.getData();\n * const urls = data.items.map((item) => `https://example.com/u/${item.userId}/list/${item.listId}`);\n * return urls;\n * }\n * ```\n */\n startUrlsFromFunction?: string;\n}\n\n/** Common input fields related to logging setup */\nexport interface LoggingActorInput {\n logLevel?: LogLevel;\n /**\n * Whether to send actor error reports to <a href=\"https://sentry.io/\">Sentry</a>.\n *\n * This info is used by the author of this actor to identify broken integrations,\n * and track down and fix issues.\n */\n errorSendToSentry?: boolean;\n /**\n * Dataset ID to which errors should be captured.\n *\n * Default: `'REPORTING'`.\n */\n errorReportingDatasetId?: string;\n}\n\n/** Common input fields related to proxy setup */\nexport interface ProxyActorInput {\n proxy?: Parameters<Actor['createProxyConfiguration']>[0];\n}\n\n/** Common input fields related to actor requests */\nexport interface RequestActorInput {\n /**\n * If set, only at most this many requests will be scraped.\n *\n * The count is determined from the RequestQueue that's used for the Actor run.\n *\n * This means that if `requestMaxEntries` is set to 50, but the\n * associated RequestQueue already handled 40 requests, then only 10 new requests\n * will be handled.\n */\n requestMaxEntries?: number;\n\n /**\n * Option to freely transform a request using a custom function before pushing it to the RequestQueue.\n *\n * If not set, the request will remain as is.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the second argument.\n *\n * `async (entry, { io, input, state, itemCacheKey }) => { ... }`\n */\n requestTransform?: string;\n /**\n * Use this if you need to run one-time initialization code before `requestTransform`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * `async ({ io, input, state, itemCacheKey }) => { ... }`\n */\n requestTransformBefore?: string;\n /**\n * Use this if you need to run one-time teardown code after `requestTransform`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * `async ({ io, input, state, itemCacheKey }) => { ... }`\n */\n requestTransformAfter?: string;\n\n /**\n * Option to filter a request using a custom function before pushing it to the RequestQueue.\n *\n * If not set, all requests will be included.\n *\n * This is done after `requestTransform`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the second argument.\n *\n * `async (entry, { io, input, state, itemCacheKey }) => boolean`\n */\n requestFilter?: string;\n /**\n * Use this if you need to run one-time initialization code before `requestFilter`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * `async ({ io, input, state, itemCacheKey }) => boolean`\n */\n requestFilterBefore?: string;\n /**\n * Use this if you need to run one-time initialization code after `requestFilter`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * `async ({ io, input, state, itemCacheKey }) => boolean`\n */\n requestFilterAfter?: string;\n\n /** ID of the RequestQueue to which the requests should be pushed */\n requestQueueId?: string;\n}\n\n/** Common input fields related to actor output */\nexport interface OutputActorInput {\n /**\n * If set, only at most this many entries will be scraped.\n *\n * The count is determined from the Dataset that's used for the Actor run.\n *\n * This means that if `outputMaxEntries` is set to 50, but the\n * associated Dataset already has 40 items in it, then only 10 new entries\n * will be saved.\n */\n outputMaxEntries?: number;\n /**\n * Option to select a subset of keys/fields of an entry that\n * will be pushed to the dataset.\n *\n * If not set, all fields on an entry will be pushed to the dataset.\n *\n * This is done after `outputRenameFields`.\n *\n * Keys can be nested, e.g. `\"someProp.value[0]\"`. Nested path is\n * resolved using Lodash.get().\n */\n outputPickFields?: string[];\n /**\n * Option to remap the keys before pushing the entries to the dataset.\n *\n * This is done before `outputRenameFields`.\n *\n * Keys can be nested, e.g. `\"someProp.value[0]\"`. Nested path is\n * resolved using Lodash.get().\n */\n outputRenameFields?: Record<string, string>;\n\n /**\n * Option to freely transform the output data object using a custom function before pushing it to the dataset.\n *\n * If not set, the data will remain as is.\n *\n * This is done after `outputPickFields` and `outputRenameFields`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the second argument.\n *\n * `async (entry, { io, input, state, itemCacheKey }) => { ... }`\n */\n outputTransform?: string;\n /**\n * Use this if you need to run one-time initialization code before `outputTransform`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * `async ({ io, input, state, itemCacheKey }) => { ... }`\n */\n outputTransformBefore?: string;\n /**\n * Use this if you need to run one-time teardown code after `outputTransform`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * `async ({ io, input, state, itemCacheKey }) => { ... }`\n */\n outputTransformAfter?: string;\n\n /**\n * Option to filter out the data using a custom function before pushing it to the dataset.\n *\n * If not set, all entries will be included.\n *\n * This is done after `outputPickFields`, `outputRenameFields`, and `outputTransform`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the second argument.\n *\n * `async (entry, { io, input, state, itemCacheKey }) => boolean`\n */\n outputFilter?: string;\n /**\n * Use this if you need to run one-time initialization code before `outputFilter`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * `async ({ io, input, state, itemCacheKey }) => boolean`\n */\n outputFilterBefore?: string;\n /**\n * Use this if you need to run one-time initialization code after `outputFilter`.\n *\n * The function has access to Apify's Actor class (under variable `io`), and actor's input\n * and a shared state in the first argument.\n *\n * `async ({ io, input, state, itemCacheKey }) => boolean`\n */\n outputFilterAfter?: string;\n\n /** ID or name of the dataset to which the data should be pushed */\n outputDatasetId?: string;\n\n /** ID or name of the key-value store used as cache */\n outputCacheStoreId?: string;\n /** Define fields that will be used for cache key */\n outputCachePrimaryKeys?: string[];\n /** Define whether we want to add, remove, or overwrite cached entries with results from the actor run */\n outputCacheActionOnResult?: 'add' | 'remove' | 'overwrite' | null;\n}\n\n/** Common input fields related to actor metamorphing */\nexport interface MetamorphActorInput {\n /**\n * If you want to run another actor with the same dataset after\n * this actor has finished (AKA metamorph into another actor),\n * then set the ID of the target actor.\n *\n * See https://docs.apify.com/sdk/python/docs/concepts/interacting-with-other-actors#actormetamorph\n */\n metamorphActorId?: string;\n /**\n * Tag or number of the target actor build to metamorph into (e.g. `beta` or `1.2.345`).\n *\n * See https://docs.apify.com/sdk/python/docs/concepts/interacting-with-other-actors#actormetamorph\n */\n metamorphActorBuild?: string;\n /**\n * Input passed to the follow-up (metamorph) actor.\n *\n * See https://docs.apify.com/sdk/python/docs/concepts/interacting-with-other-actors#actormetamorph\n */\n metamorphActorInput?: object;\n}\n\n/** Common input fields related to privacy setup */\nexport interface PrivacyActorInput {\n includePersonalData?: boolean;\n}\n\nconst datasetIdPattern = '^[a-zA-Z0-9][a-zA-Z0-9-]*$';\nconst datasetIdWithFieldPattern = `${datasetIdPattern.slice(0, -1)}#.+$`;\n\nconst newLine = (n: number) => '<br/>'.repeat(n);\n\nconst createHookFnExample = (\n args: Record<string, string>,\n mainCode: string,\n includeGuides: boolean\n) => {\n const formattedArgs = Object.keys(args).length ? Object.keys(args).join(', ') + ', ' : '';\n const formattedArgDesc = Object.entries(args).length\n ? Object.entries(args).map(([arg, desc]) => ` * \\`${arg}\\` - ${desc}.`)\n : ` *`;\n const formattedMainCode = mainCode\n .split('\\n')\n .map((s) => '// ' + s)\n .join('\\n');\n\n const guides = `//\n// /* ========== SEE BELOW FOR MORE EXAMPLES ========= */\n//\n// /**\n// * ======= ACCESSING DATASET ========\n// * To save/load/access entries in Dataset.\n// * Docs:\n// * - https://docs.apify.com/platform/storage/dataset\n// * - https://docs.apify.com/sdk/js/docs/guides/result-storage#dataset\n// * - https://docs.apify.com/sdk/js/docs/examples/map-and-reduce\n// */\n// // const dataset = await io.openDataset('MyDatasetId');\n// // const info = await dataset.getInfo();\n// // console.log(info.itemCount);\n// // // => 0\n//\n// /**\n// * ======= ACCESSING REMOTE DATA ========\n// * Use \\`sendRequest\\` to get data from the internet:\n// * Docs:\n// * - https://github.com/apify/got-scraping\n// */\n// // const catFact = await sendRequest.get('https://cat-fact.herokuapp.com/facts/5887e1d85c873e0011036889').json();\n// // console.log(catFact.text);\n// // // => \"Cats make about 100 different sounds. Dogs make only about 10.\",\n//\n// /**\n// * ======= USING CACHE ========\n// * To save the entry to the KeyValue cache (or retrieve it), you can use\n// * \\`itemCacheKey\\` to create the entry's ID for you:\n// */\n// // const cacheId = itemCacheKey(item, input.cachePrimaryKeys);\n// // const cache = await io.openKeyValueStore('MyStoreId');\n// // cache.setValue(cacheId, entry);`;\n\n const hookFnExample = `\n/**\n * Inputs:\n${formattedArgDesc}\n * \\`ctx.io\\` - Apify Actor class, see https://docs.apify.com/sdk/js/reference/class/Actor.\n * \\`ctx.input\\` - The input object that was passed to this Actor.\n * \\`ctx.state\\` - An object you can use to persist state across all your custom functions.\n * \\`ctx.sendRequest\\` - Fetch remote data. Uses 'got-scraping', same as Apify's \\`sendRequest\\`.\n * See https://crawlee.dev/docs/guides/got-scraping\n * \\`ctx.itemCacheKey\\` - A function you can use to get cacheID for current \\`entry\\`.\n * It takes the entry itself, and a list of properties to be used for hashing.\n * By default, you should pass \\`input.cachePrimaryKeys\\` to it.\n *\n */\n// async (${formattedArgs}{ io, input, state, sendRequest, itemCacheKey }) => {\n${formattedMainCode}\n${includeGuides ? guides : '//'}\n// };`;\n return hookFnExample;\n};\n\nconst CODE_EXAMPLES = {\n // Input\n inputExtendFromFunction: `// Example: Load Actor config from GitHub URL (public)\nconst config = await sendRequest.get('https://raw.githubusercontent.com/username/project/main/config.json').json();\n\n// Increase concurrency during off-peak hours\n// NOTE: Imagine we're targetting a small server, that can be slower during the day\nconst hours = new Date().getUTCHours();\nconst isOffPeak = hours < 6 || hours > 20;\nconfig.maxConcurrency = isOffPeak ? 8 : 3;\n\nreturn config;`,\n startUrlsFromFunction: `// Example: Create and load URLs from a Dataset by combining multiple fields\nconst dataset = await io.openDataset(datasetNameOrId);\nconst data = await dataset.getData();\nconst urls = data.items.map((item) => \\`https://example.com/u/\\${item.userId}/list/\\${item.listId}\\`);\nreturn urls;`,\n\n // Output\n outputTransform: `// Example: Add extra custom fields like aggregates\nreturn {\n ...entry,\n imagesCount: entry.images.length,\n};`,\n outputTransformBefore: `// Example: Fetch data or run code BEFORE entries are scraped.\nstate.categories = await sendRequest.get('https://example.com/my-categories').json();`,\n outputTransformAfter: `// Example: Fetch data or run code AFTER entries are scraped.\ndelete state.categories;`,\n outputFilter: `// Example: Filter entries based on number of images they have (at least 5)\nreturn entry.images.length > 5;`,\n outputFilterBefore: `// Example: Fetch data or run code BEFORE entries are scraped.\nstate.categories = await sendRequest.get('https://example.com/my-categories').json();`,\n outputFilterAfter: `// Example: Fetch data or run code AFTER entries are scraped.\ndelete state.categories;`,\n\n // Requests\n requestTransform: `// Example: Tag requests\n// (maybe because we use RequestQueue that pools multiple scrapers)\nrequest.userData.tag = \"VARIANT_A\";\nreturn requestQueue;`,\n requestTransformBefore: `// Example: Fetch data or run code BEFORE requests are processed.\nstate.categories = await sendRequest.get('https://example.com/my-categories').json();`,\n requestTransformAfter: `// Example: Fetch data or run code AFTER requests are processed.\ndelete state.categories;`,\n requestFilter: `// Example: Filter requests based on their tag\n// (maybe because we use RequestQueue that pools multiple scrapers)\nreturn request.userData.tag === \"VARIANT_A\";`,\n requestFilterBefore: `// Example: Fetch data or run code BEFORE requests are processed.\nstate.categories = await sendRequest.get('https://example.com/my-categories').json();`,\n requestFilterAfter: `// Example: Fetch data or run code AFTER requests are processed.\ndelete state.categories;`,\n};\n\n/** Common input fields related to actor input */\nexport const inputInput = {\n inputExtendUrl: createStringField({\n title: 'Extend Actor input from URL',\n type: 'string',\n editor: 'textfield',\n description: `Extend Actor input with a config from a URL.${newLine(1)}\n For example, you can store your actor input in a source control, and import it here.${newLine(1)}\n In case of a conflict (if a field is defined both in Actor input and in imported input) the Actor input overwrites the imported fields.${newLine(1)}\n The URL is requested with GET method, and must point to a JSON file containing a single object (the config).${newLine(1)}\n If you need to send a POST request or to modify the response further, use \\`inputExtendFromFunction\\` instead.`,\n example: 'https://raw.githubusercontent.com/jfairbank/programming-elm.com/master/cat-breeds.json',\n nullable: true,\n sectionCaption: 'Programmatic Input (Advanced)',\n sectionDescription:\n \"With these options you can configure other Actor options programmatically or from remote source.\",\n }), // prettier-ignore\n\n inputExtendFromFunction: createStringField({\n title: 'Extend Actor input from custom function',\n type: 'string',\n editor: 'javascript',\n description: `Extend Actor input with a config defined by a custom function.${newLine(1)}\n For example, you can store your actor input in a source control, and import it here.${newLine(1)}\n In case of a conflict (if a field is defined both in Actor input and in imported input) the Actor input overwrites the imported fields.${newLine(1)}\n The function must return an object (the config).`,\n example: createHookFnExample({}, CODE_EXAMPLES.inputExtendFromFunction, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.inputExtendFromFunction, true),\n nullable: true,\n }), // prettier-ignore\n} satisfies Record<keyof InputActorInput, Field>;\n\n/** Common input fields related to crawler setup */\nexport const crawlerInput = {\n maxRequestRetries: createIntegerField({\n title: 'maxRequestRetries',\n type: 'integer',\n description:\n 'Indicates how many times the request is retried if <a href=\"https://crawlee.dev/api/basic-crawler/interface/BasicCrawlerOptions#requestHandler\">BasicCrawlerOptions.requestHandler</a> fails.',\n example: 3,\n prefill: 3,\n minimum: 0,\n nullable: true,\n sectionCaption: 'Crawler configuration (Advanced)',\n sectionDescription:\n \"These options are applied directly to the Crawler. In majority of cases you don't need to change these. See https://crawlee.dev/api/basic-crawler/interface/BasicCrawlerOptions\",\n }),\n maxRequestsPerMinute: createIntegerField({\n title: 'maxRequestsPerMinute',\n type: 'integer',\n description:\n 'The maximum number of requests per minute the crawler should run. We can pass any positive, non-zero integer.',\n example: 120,\n prefill: 120,\n minimum: 1,\n nullable: true,\n }),\n maxRequestsPerCrawl: createIntegerField({\n title: 'maxRequestsPerCrawl',\n type: 'integer',\n description: `Maximum number of pages that the crawler will open. The crawl will stop when this limit is reached.\n ${newLine(1)} <strong>NOTE:</strong> In cases of parallel crawling, the actual number of pages visited might be slightly higher than this value.`,\n minimum: 1,\n nullable: true,\n }), // prettier-ignore\n minConcurrency: createIntegerField({\n title: 'minConcurrency',\n type: 'integer',\n description: `Sets the minimum concurrency (parallelism) for the crawl.${newLine(1)}\n <strong>WARNING:</strong> If we set this value too high with respect to the available system memory and CPU, our crawler will run extremely slow or crash. If not sure, it's better to keep the default value and the concurrency will scale up automatically.`,\n example: 1,\n prefill: 1,\n minimum: 1,\n nullable: true,\n }), // prettier-ignore\n maxConcurrency: createIntegerField({\n title: 'maxConcurrency',\n type: 'integer',\n description: 'Sets the maximum concurrency (parallelism) for the crawl.',\n minimum: 1,\n nullable: true,\n }),\n navigationTimeoutSecs: createIntegerField({\n title: 'navigationTimeoutSecs',\n type: 'integer',\n description:\n 'Timeout in which the HTTP request to the resource needs to finish, given in seconds.',\n minimum: 0,\n nullable: true,\n }),\n requestHandlerTimeoutSecs: createIntegerField({\n title: 'requestHandlerTimeoutSecs',\n type: 'integer',\n description:\n 'Timeout in which the function passed as <a href=\"https://crawlee.dev/api/basic-crawler/interface/BasicCrawlerOptions#requestHandler\">BasicCrawlerOptions.requestHandler</a> needs to finish, in seconds.',\n example: 180,\n prefill: 180,\n minimum: 0,\n nullable: true,\n }),\n keepAlive: createBooleanField({\n title: 'keepAlive',\n type: 'boolean',\n description:\n 'Allows to keep the crawler alive even if the RequestQueue gets empty. With keepAlive: true the crawler will keep running, waiting for more requests to come.',\n nullable: true,\n }),\n ignoreSslErrors: createBooleanField({\n title: 'ignoreSslErrors',\n type: 'boolean',\n description: 'If set to true, SSL certificate errors will be ignored.',\n nullable: true,\n }),\n additionalMimeTypes: createArrayField({\n title: 'additionalMimeTypes',\n type: 'array',\n description:\n 'An array of MIME types you want the crawler to load and process. By default, only text/html and application/xhtml+xml MIME types are supported.',\n editor: 'stringList',\n uniqueItems: true,\n nullable: true,\n }),\n suggestResponseEncoding: createStringField({\n title: 'suggestResponseEncoding',\n type: 'string',\n description:\n 'By default this crawler will extract correct encoding from the HTTP response headers. There are some websites which use invalid headers. Those are encoded using the UTF-8 encoding. If those sites actually use a different encoding, the response will be corrupted. You can use suggestResponseEncoding to fall back to a certain encoding, if you know that your target website uses it. To force a certain encoding, disregarding the response headers, use forceResponseEncoding.',\n editor: 'textfield',\n nullable: true,\n }),\n forceResponseEncoding: createStringField({\n title: 'forceResponseEncoding',\n type: 'string',\n description:\n 'By default this crawler will extract correct encoding from the HTTP response headers. Use forceResponseEncoding to force a certain encoding, disregarding the response headers. To only provide a default for missing encodings, use suggestResponseEncoding.',\n editor: 'textfield',\n nullable: true,\n }),\n} satisfies Record<keyof CrawlerConfigActorInput, Field>;\n\n/** Common input fields related to performance which are not part of the CrawlerConfig */\nexport const perfInput = {\n perfBatchSize: createIntegerField({\n title: 'Batch requests',\n type: 'integer',\n description: `If set, multiple Requests will be handled by a single Actor instance.${newLine(1)}\n Example: If set to 20, then up to 20 requests will be handled in a single \"go\", after which the actor instance will reset.${newLine(1)}\n <a href=\"https://docs.apify.com/platform/actors/development/performance#batch-jobs-win-over-the-single-jobs\">See Apify documentation</a>.`,\n example: 20,\n minimum: 0,\n nullable: true,\n sectionCaption: 'Performance configuration (Advanced)',\n sectionDescription: 'Standalone performance options. These are not passed to the Crawler.',\n }), // prettier-ignore\n perfBatchWaitSecs: createIntegerField({\n title: 'Wait (in seconds) between processing requests in a single batch',\n type: 'integer',\n description: `How long to wait between entries within a single batch.${newLine(1)}\n Increase this value if you're using batching and you're sending requests to the scraped website too fast.${newLine(1)}\n Example: If set to 1, then after each entry in a batch, wait 1 second before continuing.`,\n example: 1,\n minimum: 0,\n nullable: true,\n }), // prettier-ignore\n} satisfies Record<keyof PerfActorInput, Field>;\n\n/** Common input fields for defining URLs to scrape */\nexport const startUrlsInput = {\n startUrls: createArrayField({\n title: 'Start URLs',\n type: 'array',\n description: `List of URLs to scrape.`,\n editor: 'requestListSources',\n sectionCaption: 'Starting URLs',\n }),\n startUrlsFromDataset: createStringField({\n title: 'Start URLs from Dataset',\n type: 'string',\n editor: 'textfield',\n description: `Import URLs to scrape from an existing Dataset.${newLine(1)}\n The dataset and the field to import from should be written as \\`{datasetID}#{field}\\`.${newLine(1)}\n Example: \\`datasetid123#url\\` will take URLs from dataset \\`datasetid123\\` from field \\`url\\`.`,\n pattern: datasetIdWithFieldPattern,\n example: 'datasetid123#url',\n nullable: true,\n }), // prettier-ignore\n startUrlsFromFunction: createStringField({\n title: 'Start URLs from custom function',\n type: 'string',\n description: `Import or generate URLs to scrape using a custom function.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.startUrlsFromFunction, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.startUrlsFromFunction, true),\n nullable: true,\n }), // prettier-ignore\n} satisfies Record<keyof StartUrlsActorInput, Field>;\n\n/** Common input fields related to logging setup */\nexport const loggingInput = {\n logLevel: createStringField<LogLevel>({\n title: 'Log Level',\n type: 'string',\n editor: 'select',\n description: 'Select how detailed should be the logging.',\n enum: ['off', 'debug', 'info', 'warn', 'error'] satisfies LogLevel[],\n enumTitles: [\n 'No logging (off)',\n 'Debug and higher priority',\n 'Info and higher priority',\n 'Warning and higher priority',\n 'Error and higher priority',\n ],\n example: 'info',\n prefill: 'info',\n default: 'info',\n nullable: true,\n sectionCaption: 'Logging & Error handling (Advanced)',\n sectionDescription:\n 'Configure how to handle errors or what should be displayed in the log console.',\n }),\n errorReportingDatasetId: createStringField({\n title: 'Error reporting dataset ID',\n type: 'string',\n editor: 'textfield',\n description: `Dataset ID to which errors should be captured.${newLine(1)}\n Default: \\`'REPORTING'\\`.${newLine(1)}\n <strong>NOTE:</strong> Dataset name can only contain letters 'a' through 'z', the digits '0' through '9', and the hyphen ('-') but only in the middle of the string (e.g. 'my-value-1')`,\n example: 'REPORTING',\n prefill: 'REPORTING',\n default: 'REPORTING',\n pattern: datasetIdPattern,\n nullable: true,\n }),\n errorSendToSentry: createBooleanField({\n title: 'Send errors to Sentry',\n type: 'boolean',\n editor: 'checkbox',\n description: `Whether to send actor error reports to <a href=\"https://sentry.io/\">Sentry</a>.${newLine(1)}\n This info is used by the author of this actor to identify broken integrations,\n and track down and fix issues.`,\n example: true,\n default: true,\n nullable: true,\n }), // prettier-ignore\n} satisfies Record<keyof LoggingActorInput, Field>;\n\n/** Common input fields related to proxy setup */\nexport const proxyInput = {\n proxy: createObjectField({\n title: 'Proxy configuration',\n type: 'object',\n description: 'Select proxies to be used by your crawler.',\n editor: 'proxy',\n sectionCaption: 'Proxy',\n sectionDescription: 'Configure the proxy',\n }),\n} satisfies Record<keyof ProxyActorInput, Field>;\n\n/** Common input fields related to proxy setup */\nexport const privacyInput = {\n includePersonalData: createBooleanField({\n title: 'Include personal data',\n type: 'boolean',\n description: `By default, fields that are potential personal data are censored. Toggle this option on to get the un-uncensored values.${newLine(1)}\n <strong>WARNING:</strong> Turn this on ONLY if you have consent, legal basis for using the data, or at your own risk. <a href=\"https://gdpr.eu/eu-gdpr-personal-data/\">Learn more</a>`,\n default: false,\n example: false,\n nullable: true,\n sectionCaption: 'Privacy & Data governance (GDPR)',\n }), // prettier-ignore\n} satisfies Record<keyof PrivacyActorInput, Field>;\n\n/** Common input fields related to actor request */\nexport const requestInput = {\n requestMaxEntries: createIntegerField({\n title: 'Limit the number of requests',\n type: 'integer',\n description: `If set, only at most this many requests will be processed.${newLine(1)}\n The count is determined from the RequestQueue that's used for the Actor run.${newLine(1)}\n This means that if \\`requestMaxEntries\\` is set to 50, but the associated queue already handled 40 requests, then only 10 new requests will be handled.`,\n example: 50,\n prefill: 50,\n minimum: 0,\n nullable: true,\n sectionCaption: 'Requests limit, transformation & filtering (Advanced)',\n }), // prettier-ignore\n\n requestTransform: createStringField({\n title: 'Transform requests',\n type: 'string',\n description: `Freely transform the request object using a custom function.${newLine(1)}\n If not set, the request will remain as is.`,\n editor: 'javascript',\n example: createHookFnExample({ request: 'Request holding URL to be scraped' }, CODE_EXAMPLES.requestTransform, false),\n prefill: createHookFnExample({ request: 'Request holding URL to be scraped' }, CODE_EXAMPLES.requestTransform, true),\n nullable: true,\n }), // prettier-ignore\n requestTransformBefore: createStringField({\n title: 'Transform requests - Setup',\n type: 'string',\n description: `Use this if you need to run one-time initialization code before \\`requestTransform\\`.`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.requestTransformBefore, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.requestTransformBefore, true),\n nullable: true,\n }), // prettier-ignore\n requestTransformAfter: createStringField({\n title: 'Transform requests - Teardown',\n type: 'string',\n description: `Use this if you need to run one-time teardown code after \\`requestTransform\\`.`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.requestTransformAfter, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.requestTransformAfter, true),\n nullable: true,\n }), // prettier-ignore\n\n requestFilter: createStringField({\n title: 'Filter requests',\n type: 'string',\n description: `Decide which requests should be processed by using a custom function.${newLine(1)}\n If not set, all requests will be included.${newLine(1)}\n This is done after \\`requestTransform\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({ request: 'Request holding URL to be scraped' }, CODE_EXAMPLES.requestFilter, false),\n prefill: createHookFnExample({ request: 'Request holding URL to be scraped' }, CODE_EXAMPLES.requestFilter, true),\n nullable: true,\n }), // prettier-ignore\n requestFilterBefore: createStringField({\n title: 'Filter requests - Setup',\n type: 'string',\n description: `Use this if you need to run one-time initialization code before \\`requestFilter\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.requestFilterBefore, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.requestFilterBefore, true),\n nullable: true,\n }), // prettier-ignore\n requestFilterAfter: createStringField({\n title: 'Filter requests - Teardown',\n type: 'string',\n description: `Use this if you need to run one-time teardown code after \\`requestFilter\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.requestFilterAfter, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.requestFilterAfter, true),\n nullable: true,\n }), // prettier-ignore\n\n requestQueueId: createStringField({\n title: 'RequestQueue ID',\n type: 'string',\n description: `By default, requests are stored in the default request queue.\n Set this option if you want to use a non-default queue.\n <a href=\"https://docs.apify.com/sdk/python/docs/concepts/storages#opening-named-and-unnamed-storages\">Learn more</a>${newLine(1)}\n <strong>NOTE:</strong> RequestQueue name can only contain letters 'a' through 'z', the digits '0' through '9', and the hyphen ('-') but only in the middle of the string (e.g. 'my-value-1')`,\n editor: 'textfield',\n example: 'mIJVZsRQrDQf4rUAf',\n pattern: datasetIdPattern,\n nullable: true,\n }), // prettier-ignore\n} satisfies Record<keyof RequestActorInput, Field>;\n\n/** Common input fields related to actor output */\nexport const outputInput = {\n outputMaxEntries: createIntegerField({\n title: 'Limit the number of scraped entries',\n type: 'integer',\n description: `If set, only at most this many entries will be scraped.${newLine(1)}\n The count is determined from the Dataset that's used for the Actor run.${newLine(1)}\n This means that if \\`outputMaxEntries\\` is set to 50, but the associated Dataset already has 40 items in it, then only 10 new entries will be saved.`,\n example: 50,\n prefill: 50,\n minimum: 0,\n nullable: true,\n sectionCaption: 'Output size, transformation & filtering (T in ETL) (Advanced)',\n }),\n outputRenameFields: createObjectField({\n title: 'Rename dataset fields',\n type: 'object',\n description: `Rename fields (columns) of the output data.${newLine(1)}\n If not set, all fields will have their original names.${newLine(1)}\n This is done before \\`outputPickFields\\`.${newLine(1)}\n Keys can be nested, e.g. \\`\"someProp.value[0]\"\\`.\n Nested path is resolved using <a href=\"https://lodash.com/docs/4.17.15#get\">Lodash.get()</a>.`,\n editor: 'json',\n example: { oldFieldName: 'newFieldName' },\n nullable: true,\n }),\n outputPickFields: createArrayField({\n title: 'Pick dataset fields',\n type: 'array',\n description: `Select a subset of fields of an entry that will be pushed to the dataset.${newLine(1)}\n If not set, all fields on an entry will be pushed to the dataset.${newLine(1)}\n This is done after \\`outputRenameFields\\`.${newLine(1)}\n Keys can be nested, e.g. \\`\"someProp.value[0]\"\\`.\n Nested path is resolved using <a href=\"https://lodash.com/docs/4.17.15#get\">Lodash.get()</a>.`,\n editor: 'stringList',\n example: ['fieldName', 'another.nested[0].field'],\n nullable: true,\n }), // prettier-ignore\n\n outputTransform: createStringField({\n title: 'Transform entries',\n type: 'string',\n description: `Freely transform the output data object using a custom function.${newLine(1)}\n If not set, the data will remain as is.${newLine(1)}\n This is done after \\`outputPickFields\\` and \\`outputRenameFields\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({ entry: 'Scraped entry' }, CODE_EXAMPLES.outputTransform, false),\n prefill: createHookFnExample({ entry: 'Scraped entry' }, CODE_EXAMPLES.outputTransform, true),\n nullable: true,\n }), // prettier-ignore\n outputTransformBefore: createStringField({\n title: 'Transform entries - Setup',\n type: 'string',\n description: `Use this if you need to run one-time initialization code before \\`outputTransform\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.outputTransformBefore, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.outputTransformBefore, true),\n nullable: true,\n }), // prettier-ignore\n outputTransformAfter: createStringField({\n title: 'Transform entries - Teardown',\n type: 'string',\n description: `Use this if you need to run one-time teardown code after \\`outputTransform\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.outputTransformAfter, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.outputTransformAfter, true),\n nullable: true,\n }), // prettier-ignore\n\n outputFilter: createStringField({\n title: 'Filter entries',\n type: 'string',\n description: `Decide which scraped entries should be included in the output by using a custom function.${newLine(1)}\n If not set, all scraped entries will be included.${newLine(1)}\n This is done after \\`outputPickFields\\`, \\`outputRenameFields\\`, and \\`outputTransform\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({ entry: 'Scraped entry' }, CODE_EXAMPLES.outputFilter, false),\n prefill: createHookFnExample({ entry: 'Scraped entry' }, CODE_EXAMPLES.outputFilter, true),\n nullable: true,\n }), // prettier-ignore\n outputFilterBefore: createStringField({\n title: 'Filter entries - Setup',\n type: 'string',\n description: `Use this if you need to run one-time initialization code before \\`outputFilter\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.outputFilterBefore, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.outputFilterBefore, true),\n nullable: true,\n }), // prettier-ignore\n outputFilterAfter: createStringField({\n title: 'Filter entries - Teardown',\n type: 'string',\n description: `Use this if you need to run one-time teardown code after \\`outputFilter\\`.${newLine(1)}`,\n editor: 'javascript',\n example: createHookFnExample({}, CODE_EXAMPLES.outputFilterAfter, false),\n prefill: createHookFnExample({}, CODE_EXAMPLES.outputFilterAfter, true),\n nullable: true,\n }), // prettier-ignore\n\n outputDatasetId: createStringField({\n title: 'Dataset ID',\n type: 'string',\n description: `By default, data is written to Default dataset.\n Set this option if you want to write data to non-default dataset.\n <a href=\"https://docs.apify.com/sdk/python/docs/concepts/storages#opening-named-and-unnamed-storages\">Learn more</a>${newLine(1)}\n <strong>NOTE:</strong> Dataset name can only contain letters 'a' through 'z', the digits '0' through '9', and the hyphen ('-') but only in the middle of the string (e.g. 'my-value-1')`,\n editor: 'textfield',\n example: 'mIJVZsRQrDQf4rUAf',\n pattern: datasetIdPattern,\n nullable: true,\n sectionCaption: 'Output Dataset & Caching (L in ETL) (Advanced)',\n }), // prettier-ignore\n\n outputCacheStoreId: createStringField({\n title: 'Cache ID',\n type: 'string',\n description: `Set this option if you want to cache scraped entries in <a href=\"https://docs.apify.com/sdk/js/docs/guides/result-storage#key-value-store\">Apify's Key-value store</a>.${newLine(1)}\n This is useful for example when you want to scrape only NEW entries. In such case, you can use the \\`outputFilter\\` option to define a custom function to filter out entries already found in the cache.\n <a href=\"https://docs.apify.com/sdk/python/docs/concepts/storages#working-with-key-value-stores\">Learn more</a>${newLine(1)}\n <strong>NOTE:</strong> Cache name can only contain letters 'a' through 'z', the digits '0' through '9', and the hyphen ('-') but only in the middle of the string (e.g. 'my-value-1')`,\n editor: 'textfield',\n example: 'mIJVZsRQrDQf4rUAf',\n pattern: datasetIdPattern,\n nullable: true,\n }), // prettier-ignore\n outputCachePrimaryKeys: createArrayField<string[]>({\n title: 'Cache primary keys',\n type: 'array',\n description: `Specify fields that uniquely identify entries (primary keys), so entries can be compared against the cache.${newLine(1)}\n <strong>NOTE:</strong> If not set, the entries are hashed based on all fields`,\n editor: 'stringList',\n example: ['name', 'city'],\n nullable: true,\n }), // prettier-ignore\n outputCacheActionOnResult: createStringField<\n NonNullable<OutputActorInput['outputCacheActionOnResult']>\n >({\n title: 'Cache action on result',\n type: 'string',\n description: `Specify whether scraped results should be added to, removed from, or overwrite the cache.${newLine(1)}\n - <strong>add<strong> - Adds scraped results to the cache${newLine(1)}\n - <strong>remove<strong> - Removes scraped results from the cache${newLine(1)}\n - <strong>set<strong> - First clears all entries from the cache, then adds scraped results to the cache${newLine(1)}\n <strong>NOTE:</strong> No action happens when this field is empty.`,\n editor: 'select',\n enum: ['add', 'remove', 'overwrite'],\n example: 'add',\n nullable: true,\n }), // prettier-ignore\n} satisfies Record<keyof OutputActorInput, Field>;\n\n/** Common input fields related to actor metamorphing */\nexport const metamorphInput = {\n metamorphActorId: createStringField({\n title: 'Metamorph actor ID - metamorph to another actor at the end',\n type: 'string',\n description: `Use this option if you want to run another actor with the same dataset after this actor has finished (AKA metamorph into another actor). <a href=\"https://docs.apify.com/sdk/python/docs/concepts/interacting-with-other-actors#actormetamorph\">Learn more</a> ${newLine(1)}\n New actor is identified by its ID, e.g. \"apify/web-scraper\".`,\n editor: 'textfield',\n example: 'apify/web-scraper',\n nullable: true,\n sectionCaption: 'Integrations (Metamorphing) (Advanced)',\n }), // prettier-ignore\n metamorphActorBuild: createStringField({\n title: 'Metamorph actor build',\n type: 'string',\n description: `Tag or number of the target actor build to metamorph into (e.g. 'beta' or '1.2.345')`,\n editor: 'textfield',\n example: '1.2.345',\n nullable: true,\n }),\n metamorphActorInput: createObjectField({\n title: 'Metamorph actor input',\n type: 'object',\n description: `Input object passed to the follow-up (metamorph) actor. <a href=\"https://docs.apify.com/sdk/python/docs/concepts/interacting-with-other-actors#actormetamorph\">Learn more</a>`,\n editor: 'json',\n example: { uploadDatasetToGDrive: true },\n nullable: true,\n }),\n} satisfies Record<keyof MetamorphActorInput, Field>;\n\nexport const allActorInputs = {\n ...inputInput,\n ...startUrlsInput,\n ...proxyInput,\n ...privacyInput,\n ...requestInput,\n ...outputInput,\n ...crawlerInput,\n ...perfInput,\n ...loggingInput,\n ...metamorphInput,\n} satisfies Record<keyof AllActorInputs, Field>;\n\nexport const crawlerInputValidationFields = {\n navigationTimeoutSecs: Joi.number().integer().min(0).optional(),\n ignoreSslErrors: Joi.boolean().optional(),\n additionalMimeTypes: Joi.array().items(Joi.string().min(1)).optional(),\n suggestResponseEncoding: Joi.string().min(1).optional(),\n forceResponseEncoding: Joi.string().min(1).optional(),\n requestHandlerTimeoutSecs: Joi.number().integer().min(0).optional(),\n maxRequestRetries: Joi.number().integer().min(0).optional(),\n maxRequestsPerCrawl: Joi.number().integer().min(0).optional(),\n maxRequestsPerMinute: Joi.number().integer().min(0).optional(),\n minConcurrency: Joi.number().integer().min(0).optional(),\n maxConcurrency: Joi.number().integer().min(0).optional(),\n keepAlive: Joi.boolean().optional(),\n} satisfies Record<keyof CrawlerConfigActorInput, Joi.Schema>;\n\nexport const perfInputValidationFields = {\n perfBatchSize: Joi.number().integer().min(0).optional(),\n perfBatchWaitSecs: Joi.number().integer().min(0).optional(),\n} satisfies Record<keyof PerfActorInput, Joi.Schema>;\n\nexport const inputInputValidationFields = {\n inputExtendUrl: Joi.string().min(1).uri().optional(),\n inputExtendFromFunction: Joi.string().min(1).optional(),\n} satisfies Record<keyof InputActorInput, Joi.Schema>;\n\nexport const startUrlsInputValidationFields = {\n startUrls: Joi.array().items(Joi.string().min(1), Joi.object()).optional(),\n startUrlsFromDataset: Joi.string().min(1).pattern(new RegExp(datasetIdWithFieldPattern)).optional(), // prettier-ignore\n startUrlsFromFunction: Joi.string().min(1).optional(),\n} satisfies Record<keyof StartUrlsActorInput, Joi.Schema>;\n\nexport const loggingInputValidationFields = {\n logLevel: Joi.string().valid(...LOG_LEVEL).optional(), // prettier-ignore\n errorReportingDatasetId: Joi.string().min(1).pattern(new RegExp(datasetIdPattern)).optional(), // prettier-ignore\n errorSendToSentry: Joi.boolean().optional(),\n} satisfies Record<keyof LoggingActorInput, Joi.Schema>;\n\nexport const proxyInputValidationFields = {\n proxy: Joi.object().optional(), // NOTE: Expand this type?\n} satisfies Record<keyof ProxyActorInput, Joi.Schema>;\n\nexport const privacyInputValidationFields = {\n includePersonalData: Joi.boolean().optional(),\n} satisfies Record<keyof PrivacyActorInput, Joi.Schema>;\n\nexport const requestInputValidationFields = {\n requestMaxEntries: Joi.number().integer().min(0).optional(),\n\n requestTransform: Joi.string().min(1).optional(),\n requestTransformBefore: Joi.string().min(1).optional(),\n requestTransformAfter: Joi.string().min(1).optional(),\n requestFilter: Joi.string().min(1).optional(),\n requestFilterBefore: Joi.string().min(1).optional(),\n requestFilterAfter: Joi.string().min(1).optional(),\n\n requestQueueId: Joi.string().min(1).pattern(new RegExp(datasetIdPattern)).optional(), // prettier-ignore\n} satisfies Record<keyof RequestActorInput, Joi.Schema>;\n\nexport const outputInputValidationFields = {\n outputMaxEntries: Joi.number().integer().min(0).optional(),\n\n outputPickFields: Joi.array().items(Joi.string().min(1)).optional(),\n // https://stackoverflow.com/a/49898360/9788634\n outputRenameFields: Joi.object().pattern(/./, Joi.string().min(1)).optional(),\n\n outputTransform: Joi.string().min(1).optional(),\n outputTransformBefore: Joi.string().min(1).optional(),\n outputTransformAfter: Joi.string().min(1).optional(),\n outputFilter: Joi.string().min(1).optional(),\n outputFilterBefore: Joi.string().min(1).optional(),\n outputFilterAfter: Joi.string().min(1).optional(),\n\n outputCacheStoreId: Joi.string().min(1).pattern(new RegExp(datasetIdPattern)).optional(), // prettier-ignore\n outputCachePrimaryKeys: Joi.array().items(Joi.string().min(1)).optional(),\n outputCacheActionOnResult: Joi.string().min(1).allow('add', 'remove', 'overwrite').optional(), // prettier-ignore\n\n outputDatasetId: Joi.string().min(1).pattern(new RegExp(datasetIdPattern)).optional(), // prettier-ignore\n} satisfies Record<keyof OutputActorInput, Joi.Schema>;\n\nexport const metamorphInputValidationFields = {\n metamorphActorId: Joi.string().min(1).optional(),\n metamorphActorBuild: Joi.string().min(1).optional(),\n metamorphActorInput: Joi.object().unknown(true).optional(),\n} satisfies Record<keyof MetamorphActorInput, Joi.Schema>;\n\nexport const allActorInputValidationFields = {\n ...inputInputValidationFields,\n ...startUrlsInputValidationFields,\n ...proxyInputValidationFields,\n ...privacyInputValidationFields,\n ...requestInputValidationFields,\n ...outputInputValidationFields,\n ...crawlerInputValidationFields,\n ...perfInputValidationFields,\n ...loggingInputValidationFields,\n ...metamorphInputValidationFields,\n} satisfies Record<keyof AllActorInputs, Joi.Schema>;\n"]}
@@ -0,0 +1,30 @@
1
+ import { Log } from 'apify';
2
+ /**
3
+ * Given a batch of entries, use several strategies to check
4
+ * if we've reached the limit on the max number of entries
5
+ * we're allowed to extract this run.
6
+ */
7
+ export declare const checkEntriesCount: ({ maxCount, currBatchCount, datasetNameOrId, customItemCount, }: {
8
+ /** Number of entries in the current batch */
9
+ currBatchCount: number;
10
+ /** Max number of entries allowed to extract. */
11
+ maxCount?: number | null | undefined;
12
+ /**
13
+ * If given, maxCount will be ALSO compared against
14
+ * the amount of entries already in the dataset.
15
+ */
16
+ datasetNameOrId?: string | null | undefined;
17
+ /**
18
+ * If given, maxCount will be ALSO compared against
19
+ * this amount.
20
+ */
21
+ customItemCount?: number | null | undefined;
22
+ }, { log }?: {
23
+ log?: Log | undefined;
24
+ }) => Promise<{
25
+ limitReached: boolean;
26
+ overflow: number;
27
+ }>;
28
+ export declare const getDatasetCount: (datasetNameOrId?: string, { log }?: {
29
+ log?: Log | undefined;
30
+ }) => Promise<number | null>;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getDatasetCount = exports.checkEntriesCount = void 0;
13
+ const apify_1 = require("apify");
14
+ /**
15
+ * Given a batch of entries, use several strategies to check
16
+ * if we've reached the limit on the max number of entries
17
+ * we're allowed to extract this run.
18
+ */
19
+ const checkEntriesCount = ({ maxCount, currBatchCount, datasetNameOrId, customItemCount, }, { log } = {}) => __awaiter(void 0, void 0, void 0, function* () {
20
+ const datasetItemCount = datasetNameOrId ? yield (0, exports.getDatasetCount)(datasetNameOrId, { log }) : null;
21
+ if ((datasetItemCount == null && customItemCount == null) || maxCount == null) {
22
+ return { limitReached: false, overflow: 0 };
23
+ }
24
+ // Check if we've reached the limit for max entries
25
+ if (currBatchCount >= maxCount) {
26
+ return { limitReached: true, overflow: currBatchCount - maxCount };
27
+ }
28
+ // Use count of items already in dataset to check if limit reached
29
+ if (datasetItemCount != null && datasetItemCount + currBatchCount >= maxCount) {
30
+ return { limitReached: true, overflow: datasetItemCount + currBatchCount - maxCount };
31
+ }
32
+ // Use page offset to check if limit reached (20 entries per page)
33
+ if (customItemCount != null && customItemCount >= maxCount) {
34
+ return { limitReached: true, overflow: customItemCount - maxCount };
35
+ }
36
+ return { limitReached: false, overflow: 0 };
37
+ });
38
+ exports.checkEntriesCount = checkEntriesCount;
39
+ const getDatasetCount = (datasetNameOrId, { log } = {}) => __awaiter(void 0, void 0, void 0, function* () {
40
+ var _a;
41
+ log === null || log === void 0 ? void 0 : log.debug('Opening dataset');
42
+ const dataset = yield apify_1.Actor.openDataset(datasetNameOrId);
43
+ log === null || log === void 0 ? void 0 : log.debug('Obtaining dataset entries count');
44
+ const datasetInfo = yield dataset.getInfo();
45
+ const count = (_a = datasetInfo === null || datasetInfo === void 0 ? void 0 : datasetInfo.itemCount) !== null && _a !== void 0 ? _a : null;
46
+ if (typeof count !== 'number') {
47
+ log === null || log === void 0 ? void 0 : log.warning('Failed to get count of entries in dataset. We use this info to know how many items were scraped. More entries might be scraped than was set.'); // prettier-ignore
48
+ }
49
+ else {
50
+ log === null || log === void 0 ? void 0 : log.debug(`Done obtaining dataset entries count (${count})`);
51
+ }
52
+ return count;
53
+ });
54
+ exports.getDatasetCount = getDatasetCount;
55
+ //# sourceMappingURL=maxCount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maxCount.js","sourceRoot":"","sources":["../../../../src/lib/dataset/maxCount.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,iCAAmC;AAEnC;;;;GAIG;AACI,MAAM,iBAAiB,GAAG,CAC/B,EACE,QAAQ,EACR,cAAc,EACd,eAAe,EACf,eAAe,GAgBhB,EACD,EAAE,GAAG,KAAoB,EAAE,EAC3B,EAAE;IACF,MAAM,gBAAgB,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM,IAAA,uBAAe,EAAC,eAAe,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAElG,IAAI,CAAC,gBAAgB,IAAI,IAAI,IAAI,eAAe,IAAI,IAAI,CAAC,IAAI,QAAQ,IAAI,IAAI,EAAE;QAC7E,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;KAC7C;IAED,mDAAmD;IACnD,IAAI,cAAc,IAAI,QAAQ,EAAE;QAC9B,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,GAAG,QAAQ,EAAE,CAAC;KACpE;IAED,kEAAkE;IAClE,IAAI,gBAAgB,IAAI,IAAI,IAAI,gBAAgB,GAAG,cAAc,IAAI,QAAQ,EAAE;QAC7E,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,GAAG,cAAc,GAAG,QAAQ,EAAE,CAAC;KACvF;IAED,kEAAkE;IAClE,IAAI,eAAe,IAAI,IAAI,IAAI,eAAe,IAAI,QAAQ,EAAE;QAC1D,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,GAAG,QAAQ,EAAE,CAAC;KACrE;IAED,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAC9C,CAAC,CAAA,CAAC;AA9CW,QAAA,iBAAiB,qBA8C5B;AAEK,MAAM,eAAe,GAAG,CAAO,eAAwB,EAAE,EAAE,GAAG,KAAoB,EAAE,EAAE,EAAE;;IAC7F,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,MAAM,aAAK,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;IACzD,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,SAAS,mCAAI,IAAI,CAAC;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC7B,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,CAAC,8IAA8I,CAAC,CAAC,CAAC,kBAAkB;KACjL;SAAM;QACL,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,KAAK,CAAC,yCAAyC,KAAK,GAAG,CAAC,CAAC;KAC/D;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAA,CAAC;AAZW,QAAA,eAAe,mBAY1B","sourcesContent":["import { Actor, Log } from 'apify';\n\n/**\n * Given a batch of entries, use several strategies to check\n * if we've reached the limit on the max number of entries\n * we're allowed to extract this run.\n */\nexport const checkEntriesCount = async (\n {\n maxCount,\n currBatchCount,\n datasetNameOrId,\n customItemCount,\n }: {\n /** Number of entries in the current batch */\n currBatchCount: number;\n /** Max number of entries allowed to extract. */\n maxCount?: number | null;\n /**\n * If given, maxCount will be ALSO compared against\n * the amount of entries already in the dataset.\n */\n datasetNameOrId?: string | null;\n /**\n * If given, maxCount will be ALSO compared against\n * this amount.\n */\n customItemCount?: number | null;\n },\n { log }: { log?: Log } = {}\n) => {\n const datasetItemCount = datasetNameOrId ? await getDatasetCount(datasetNameOrId, { log }) : null;\n\n if ((datasetItemCount == null && customItemCount == null) || maxCount == null) {\n return { limitReached: false, overflow: 0 };\n }\n\n // Check if we've reached the limit for max entries\n if (currBatchCount >= maxCount) {\n return { limitReached: true, overflow: currBatchCount - maxCount };\n }\n\n // Use count of items already in dataset to check if limit reached\n if (datasetItemCount != null && datasetItemCount + currBatchCount >= maxCount) {\n return { limitReached: true, overflow: datasetItemCount + currBatchCount - maxCount };\n }\n\n // Use page offset to check if limit reached (20 entries per page)\n if (customItemCount != null && customItemCount >= maxCount) {\n return { limitReached: true, overflow: customItemCount - maxCount };\n }\n\n return { limitReached: false, overflow: 0 };\n};\n\nexport const getDatasetCount = async (datasetNameOrId?: string, { log }: { log?: Log } = {}) => {\n log?.debug('Opening dataset');\n const dataset = await Actor.openDataset(datasetNameOrId);\n log?.debug('Obtaining dataset entries count');\n const datasetInfo = await dataset.getInfo();\n const count = datasetInfo?.itemCount ?? null;\n if (typeof count !== 'number') {\n log?.warning('Failed to get count of entries in dataset. We use this info to know how many items were scraped. More entries might be scraped than was set.'); // prettier-ignore\n } else {\n log?.debug(`Done obtaining dataset entries count (${count})`);\n }\n return count;\n};\n"]}
@@ -0,0 +1,123 @@
1
+ import type { CrawlingContext } from 'crawlee';
2
+ export interface ActorEntryMetadata {
3
+ actorId: string | null;
4
+ actorRunId: string | null;
5
+ actorRunUrl: string | null;
6
+ contextId: string;
7
+ requestId: string | null;
8
+ /** The URL given to the crawler */
9
+ originalUrl: string | null;
10
+ /** The URL given to the crawler after possible redirects */
11
+ loadedUrl: string | null;
12
+ /** ISO datetime string that indicates the time when the request has been processed. */
13
+ dateHandled: string;
14
+ numberOfRetries: number;
15
+ }
16
+ /** Add metadata to the object */
17
+ export type WithActorEntryMetadata<T> = T & {
18
+ metadata: ActorEntryMetadata;
19
+ };
20
+ /** Functions that generates a "redacted" version of a value */
21
+ export type PrivateValueGen<V, K, O> = (val: V, key: K, obj: O) => any;
22
+ /**
23
+ * Given a property value (and its position) this function
24
+ * determines if the property is considered private (and
25
+ * hence should be hidden for privacy reasons).
26
+ *
27
+ * Property is private if the function returns truthy value.
28
+ */
29
+ export type PrivacyFilter<V, K, O> = (val: V, key: K, obj: O, options?: {
30
+ setCustomPrivateValue: (val: V) => any;
31
+ privateValueGen: PrivateValueGen<V, K, O>;
32
+ }) => any;
33
+ /**
34
+ * PrivacyMask determines which (potentally nested) properties
35
+ * of an object are considered private.
36
+ *
37
+ * PrivacyMask copies the structure of another object, but each
38
+ * non-object property on PrivacyMask is a PrivacyFilter - function
39
+ * that determines if the property is considered private.
40
+ *
41
+ * Property is private if the function returns truthy value.
42
+ */
43
+ export type PrivacyMask<T extends object> = {
44
+ [Key in keyof T]?: T[Key] extends Date | any[] ? PrivacyFilter<T[Key], Key, T> : T[Key] extends object ? PrivacyMask<T[Key]> : PrivacyFilter<T[Key], Key, T>;
45
+ };
46
+ export interface PushDataOptions<T extends object> {
47
+ /**
48
+ * Whether items should be enriched with request and run metadata.
49
+ *
50
+ * If truthy, the metadata is set under the `metadata` property.
51
+ */
52
+ includeMetadata?: boolean;
53
+ /**
54
+ * Whether properties that are considered personal data should be shown as is.
55
+ *
56
+ * If falsy or not set, these properties are redacted to hide the actual information.
57
+ *
58
+ * Which properties are personal data is determined by `privacyMask`.
59
+ */
60
+ showPrivate?: boolean;
61
+ /**
62
+ * Determine which properties are considered personal data.
63
+ *
64
+ * See {@link PrivacyMask}.
65
+ **/
66
+ privacyMask: PrivacyMask<T>;
67
+ /**
68
+ * Option to select which keys (fields) of an entry to keep (discarding the rest)
69
+ * before pushing the entries to the dataset.
70
+ *
71
+ * This serves mainly to allow users to select the keys from actor input UI.
72
+ *
73
+ * This is done before `remapKeys`.
74
+ *
75
+ * Keys can be nested, e.g. `"someProp.value[0]"`. Nested path is
76
+ * resolved using Lodash.get().
77
+ */
78
+ pickKeys?: string[];
79
+ /**
80
+ * Option to remap the keys before pushing the entries to the dataset.
81
+ *
82
+ * This serves mainly to allow users to remap the keys from actor input UI.
83
+ *
84
+ * Keys can be nested, e.g. `"someProp.value[0]"`. Nested path is
85
+ * resolved using Lodash.get().
86
+ */
87
+ remapKeys?: Record<string, string>;
88
+ /**
89
+ * Option to freely transform an entry before pushing it to the dataset.
90
+ *
91
+ * This serves mainly to allow users to transform the entries from actor input UI.
92
+ */
93
+ transform?: (item: any) => any;
94
+ /**
95
+ * Option to filter an entry before pushing it to the dataset.
96
+ *
97
+ * This serves mainly to allow users to filter the entries from actor input UI.
98
+ */
99
+ filter?: (item: any) => any;
100
+ /** ID or name of the dataset to which the data should be pushed */
101
+ datasetIdOrName?: string;
102
+ /** ID or name of the key-value store used as cache */
103
+ cacheStoreIdOrName?: string;
104
+ /** Define fields that uniquely identify entries for caching */
105
+ cachePrimaryKeys?: string[];
106
+ /** Define whether we want to add, remove, or overwrite cached entries with results from the actor run */
107
+ cacheActionOnResult?: 'add' | 'remove' | 'overwrite' | null;
108
+ }
109
+ /**
110
+ * Serialize dataset item to fixed-length hash.
111
+ *
112
+ * NOTE: Apify allows the key-value store key to be max 256 char long.
113
+ * https://docs.apify.com/sdk/js/reference/class/KeyValueStore#setValue
114
+ */
115
+ export declare const itemCacheKey: (item: any, primaryKeys?: string[]) => string;
116
+ /**
117
+ * `Actor.pushData` with extra features:
118
+ *
119
+ * - (Optionally) Add metadata to entries before they are pushed to dataset.
120
+ * - (Optionally) Set which (nested) properties are personal data and allow to
121
+ * redact them for privacy compliance.
122
+ */
123
+ export declare const pushData: <Ctx extends CrawlingContext<unknown, import("crawlee").Dictionary>, T extends Record<any, any> = Record<any, any>>(oneOrManyItems: T | T[], ctx: Ctx, options: PushDataOptions<T>) => Promise<unknown[]>;
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.pushData = exports.itemCacheKey = void 0;
13
+ const apify_1 = require("apify");
14
+ const lodash_1 = require("lodash");
15
+ const async_1 = require("../../utils/async");
16
+ const createMetadataMapper = (ctx) => {
17
+ const { actorId, actorRunId } = apify_1.Actor.getEnv();
18
+ const actorRunUrl = actorId != null && actorRunId != null
19
+ ? `https://console.apify.com/actors/${actorId}/runs/${actorRunId}`
20
+ : null;
21
+ const handledAt = new Date().toISOString();
22
+ const addMetadataToData = (item) => {
23
+ var _a, _b, _c;
24
+ return (Object.assign(Object.assign({}, item), { metadata: {
25
+ actorId,
26
+ actorRunId,
27
+ actorRunUrl,
28
+ contextId: ctx.id,
29
+ requestId: (_a = ctx.request.id) !== null && _a !== void 0 ? _a : null,
30
+ originalUrl: (_b = ctx.request.url) !== null && _b !== void 0 ? _b : null,
31
+ loadedUrl: (_c = ctx.request.loadedUrl) !== null && _c !== void 0 ? _c : null,
32
+ dateHandled: ctx.request.handledAt || handledAt,
33
+ numberOfRetries: ctx.request.retryCount,
34
+ } }));
35
+ };
36
+ return addMetadataToData;
37
+ };
38
+ const applyPrivacyMask = (item, options) => {
39
+ const { showPrivate, privacyMask, privateValueGen = (_, key) => `<Redacted property "${key}">`, } = options;
40
+ const resolvePrivateValue = (key, val) => {
41
+ // Allow to set custom "redacted" value by calling
42
+ // `setCustomPrivateValue` from inside the filter function.
43
+ let customPrivateValue;
44
+ let setCustomPrivateValueCalled = false;
45
+ const setCustomPrivateValue = (val) => {
46
+ customPrivateValue = val;
47
+ setCustomPrivateValueCalled = true;
48
+ };
49
+ const privacyFilter = privacyMask[key];
50
+ const isPrivate = privacyFilter
51
+ ? privacyFilter(val, key, item, { setCustomPrivateValue, privateValueGen })
52
+ : false;
53
+ // prettier-ignore
54
+ const privateValue = (
55
+ // Don't redact anything if we're asked to show private data
56
+ showPrivate ? val
57
+ // Otherwise, if custom value was given, use that
58
+ : setCustomPrivateValueCalled ? customPrivateValue
59
+ // Otherwise, decide based on filter truthiness
60
+ : isPrivate ? privateValueGen(val, key, item) : val);
61
+ return privateValue;
62
+ };
63
+ const redactedObj = Object.entries(item).reduce((agg, [key, val]) => {
64
+ var _a;
65
+ const isNestedObj = typeof val === 'object' && val != null && !(val instanceof Date) && !Array.isArray(val);
66
+ if (isNestedObj) {
67
+ // Recursively process nested objects
68
+ const subObj = applyPrivacyMask(val, {
69
+ showPrivate,
70
+ privacyMask: ((_a = privacyMask[key]) !== null && _a !== void 0 ? _a : {}),
71
+ privateValueGen,
72
+ });
73
+ agg[key] = subObj;
74
+ }
75
+ else {
76
+ agg[key] = resolvePrivateValue(key, val);
77
+ }
78
+ return agg;
79
+ }, {});
80
+ return redactedObj;
81
+ };
82
+ /** Rename object properties in place */
83
+ const renameKeys = (item, keyNameMap) => {
84
+ Object.entries(keyNameMap || {}).forEach(([oldPath, newPath]) => {
85
+ if (oldPath === newPath)
86
+ return;
87
+ const val = (0, lodash_1.get)(item, oldPath);
88
+ (0, lodash_1.set)(item, newPath, val);
89
+ (0, lodash_1.unset)(item, oldPath);
90
+ });
91
+ return item;
92
+ };
93
+ const sortObjectKeys = (obj) => (0, lodash_1.fromPairs)((0, lodash_1.sortBy)(Object.keys(obj)).map((key) => [key, obj[key]]));
94
+ /**
95
+ * Serialize dataset item to fixed-length hash.
96
+ *
97
+ * NOTE: Apify allows the key-value store key to be max 256 char long.
98
+ * https://docs.apify.com/sdk/js/reference/class/KeyValueStore#setValue
99
+ */
100
+ const itemCacheKey = (item, primaryKeys) => {
101
+ const thePrimaryKeys = primaryKeys
102
+ ? (0, lodash_1.sortBy)((0, lodash_1.uniq)(primaryKeys.map((s) => s === null || s === void 0 ? void 0 : s.trim()).filter(Boolean)))
103
+ : null;
104
+ const serializedItem = thePrimaryKeys
105
+ ? thePrimaryKeys.map((k) => item === null || item === void 0 ? void 0 : item[k]).join(':')
106
+ : item && (0, lodash_1.isPlainObject)(item)
107
+ ? JSON.stringify(sortObjectKeys(item)) // If possible sort the object's keys
108
+ : JSON.stringify(item);
109
+ const cacheId = cyrb53(serializedItem);
110
+ return cacheId.toString();
111
+ };
112
+ exports.itemCacheKey = itemCacheKey;
113
+ /**
114
+ * Hashing function used when calculating cache ID hash from entries.
115
+ *
116
+ * See https://stackoverflow.com/a/52171480/9788634.
117
+ */
118
+ const cyrb53 = (str, seed = 0) => {
119
+ let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
120
+ for (let i = 0, ch; i < str.length; i++) {
121
+ ch = str.charCodeAt(i);
122
+ h1 = Math.imul(h1 ^ ch, 2654435761);
123
+ h2 = Math.imul(h2 ^ ch, 1597334677);
124
+ }
125
+ h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
126
+ h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
127
+ h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
128
+ h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
129
+ return 4294967296 * (2097151 & h2) + (h1 >>> 0);
130
+ };
131
+ /**
132
+ * `Actor.pushData` with extra features:
133
+ *
134
+ * - (Optionally) Add metadata to entries before they are pushed to dataset.
135
+ * - (Optionally) Set which (nested) properties are personal data and allow to
136
+ * redact them for privacy compliance.
137
+ */
138
+ const pushData = (oneOrManyItems, ctx, options) => __awaiter(void 0, void 0, void 0, function* () {
139
+ const { includeMetadata, showPrivate, privacyMask, remapKeys, pickKeys, transform, filter, datasetIdOrName, cacheStoreIdOrName, cachePrimaryKeys, cacheActionOnResult, } = options;
140
+ const items = Array.isArray(oneOrManyItems) ? oneOrManyItems : [oneOrManyItems];
141
+ ctx.log.debug(`Preparing entries before pushing ${items.length} items to dataset`); // prettier-ignore
142
+ const addMetadataToData = createMetadataMapper(ctx);
143
+ const adjustedItems = yield items.reduce((aggPromise, item) => __awaiter(void 0, void 0, void 0, function* () {
144
+ const agg = yield aggPromise;
145
+ const itemWithMetadata = includeMetadata ? addMetadataToData(item) : item;
146
+ const maskedItem = applyPrivacyMask(itemWithMetadata, {
147
+ showPrivate,
148
+ privacyMask,
149
+ privateValueGen: (val, key) => `<Redacted property "${key}". To include the actual value, toggle ON the Actor input option "Include personal data">`,
150
+ });
151
+ const pickedItem = pickKeys ? (0, lodash_1.pick)(maskedItem, pickKeys) : maskedItem;
152
+ const renamedItem = remapKeys ? renameKeys(pickedItem, remapKeys) : pickedItem;
153
+ const transformedItem = transform ? yield transform(renamedItem) : renamedItem;
154
+ const passedFilter = filter ? yield filter(transformedItem) : true;
155
+ if (passedFilter)
156
+ agg.push(transformedItem);
157
+ return agg;
158
+ }), Promise.resolve([]));
159
+ // Push entries to primary dataset
160
+ ctx.log.info(`Pushing ${adjustedItems.length} entries to dataset`);
161
+ const dataset = datasetIdOrName ? yield apify_1.Actor.openDataset(datasetIdOrName) : apify_1.Actor;
162
+ yield dataset.pushData(adjustedItems);
163
+ ctx.log.info(`Done pushing ${adjustedItems.length} entries to dataset`);
164
+ // Update entries in cache
165
+ if (cacheStoreIdOrName && cacheActionOnResult) {
166
+ ctx.log.info(`Update ${adjustedItems.length} entries in cache`);
167
+ const store = yield apify_1.Actor.openKeyValueStore(cacheStoreIdOrName);
168
+ yield (0, async_1.serialAsyncMap)(adjustedItems, (item) => __awaiter(void 0, void 0, void 0, function* () {
169
+ const cacheId = (0, exports.itemCacheKey)(item, cachePrimaryKeys);
170
+ if (['add', 'overwrite'].includes(cacheActionOnResult)) {
171
+ yield store.setValue(cacheId, item);
172
+ }
173
+ else if (cacheActionOnResult === 'remove') {
174
+ yield store.setValue(cacheId, null);
175
+ }
176
+ }));
177
+ ctx.log.info(`Done updating ${adjustedItems.length} entries in cache`);
178
+ }
179
+ return adjustedItems;
180
+ });
181
+ exports.pushData = pushData;
182
+ //# sourceMappingURL=pushData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pushData.js","sourceRoot":"","sources":["../../../../src/lib/dataset/pushData.ts"],"names":[],"mappings":"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","sourcesContent":["import { Actor } from 'apify';\nimport type { CrawlingContext } from 'crawlee';\nimport { get, pick, set, unset, uniq, sortBy, isPlainObject, fromPairs } from 'lodash';\n\nimport { serialAsyncMap } from '../../utils/async';\n\nexport interface ActorEntryMetadata {\n actorId: string | null;\n actorRunId: string | null;\n actorRunUrl: string | null;\n contextId: string;\n requestId: string | null;\n\n /** The URL given to the crawler */\n originalUrl: string | null;\n /** The URL given to the crawler after possible redirects */\n loadedUrl: string | null;\n\n /** ISO datetime string that indicates the time when the request has been processed. */\n dateHandled: string;\n numberOfRetries: number;\n}\n\n/** Add metadata to the object */\nexport type WithActorEntryMetadata<T> = T & { metadata: ActorEntryMetadata };\n\n/** Functions that generates a \"redacted\" version of a value */\nexport type PrivateValueGen<V, K, O> = (val: V, key: K, obj: O) => any;\n\n/**\n * Given a property value (and its position) this function\n * determines if the property is considered private (and\n * hence should be hidden for privacy reasons).\n *\n * Property is private if the function returns truthy value.\n */\nexport type PrivacyFilter<V, K, O> = (\n val: V,\n key: K,\n obj: O,\n options?: {\n setCustomPrivateValue: (val: V) => any;\n privateValueGen: PrivateValueGen<V, K, O>;\n }\n) => any;\n\n/**\n * PrivacyMask determines which (potentally nested) properties\n * of an object are considered private.\n *\n * PrivacyMask copies the structure of another object, but each\n * non-object property on PrivacyMask is a PrivacyFilter - function\n * that determines if the property is considered private.\n *\n * Property is private if the function returns truthy value.\n */\nexport type PrivacyMask<T extends object> = {\n [Key in keyof T]?: T[Key] extends Date | any[] // Consider Data and Array as non-objects\n ? PrivacyFilter<T[Key], Key, T>\n : T[Key] extends object\n ? PrivacyMask<T[Key]>\n : PrivacyFilter<T[Key], Key, T>;\n};\n\nexport interface PushDataOptions<T extends object> {\n /**\n * Whether items should be enriched with request and run metadata.\n *\n * If truthy, the metadata is set under the `metadata` property.\n */\n includeMetadata?: boolean;\n /**\n * Whether properties that are considered personal data should be shown as is.\n *\n * If falsy or not set, these properties are redacted to hide the actual information.\n *\n * Which properties are personal data is determined by `privacyMask`.\n */\n showPrivate?: boolean;\n /**\n * Determine which properties are considered personal data.\n *\n * See {@link PrivacyMask}.\n **/\n privacyMask: PrivacyMask<T>;\n /**\n * Option to select which keys (fields) of an entry to keep (discarding the rest)\n * before pushing the entries to the dataset.\n *\n * This serves mainly to allow users to select the keys from actor input UI.\n *\n * This is done before `remapKeys`.\n *\n * Keys can be nested, e.g. `\"someProp.value[0]\"`. Nested path is\n * resolved using Lodash.get().\n */\n pickKeys?: string[];\n /**\n * Option to remap the keys before pushing the entries to the dataset.\n *\n * This serves mainly to allow users to remap the keys from actor input UI.\n *\n * Keys can be nested, e.g. `\"someProp.value[0]\"`. Nested path is\n * resolved using Lodash.get().\n */\n remapKeys?: Record<string, string>;\n /**\n * Option to freely transform an entry before pushing it to the dataset.\n *\n * This serves mainly to allow users to transform the entries from actor input UI.\n */\n transform?: (item: any) => any;\n /**\n * Option to filter an entry before pushing it to the dataset.\n *\n * This serves mainly to allow users to filter the entries from actor input UI.\n */\n filter?: (item: any) => any;\n /** ID or name of the dataset to which the data should be pushed */\n datasetIdOrName?: string;\n /** ID or name of the key-value store used as cache */\n cacheStoreIdOrName?: string;\n /** Define fields that uniquely identify entries for caching */\n cachePrimaryKeys?: string[];\n /** Define whether we want to add, remove, or overwrite cached entries with results from the actor run */\n cacheActionOnResult?: 'add' | 'remove' | 'overwrite' | null;\n}\n\nconst createMetadataMapper = <Ctx extends CrawlingContext>(ctx: Ctx) => {\n const { actorId, actorRunId } = Actor.getEnv();\n const actorRunUrl =\n actorId != null && actorRunId != null\n ? `https://console.apify.com/actors/${actorId}/runs/${actorRunId}`\n : null;\n const handledAt = new Date().toISOString();\n\n const addMetadataToData = <T extends Record<any, any> = Record<any, any>>(\n item\n ): WithActorEntryMetadata<T> => ({\n ...item,\n metadata: {\n actorId,\n actorRunId,\n actorRunUrl,\n contextId: ctx.id,\n requestId: ctx.request.id ?? null,\n\n originalUrl: ctx.request.url ?? null,\n loadedUrl: ctx.request.loadedUrl ?? null,\n\n dateHandled: ctx.request.handledAt || handledAt,\n numberOfRetries: ctx.request.retryCount,\n },\n });\n return addMetadataToData;\n};\n\nconst applyPrivacyMask = <T extends Record<any, any> = Record<any, any>>(\n item: T,\n options: {\n showPrivate?: boolean;\n privacyMask: PrivacyMask<T>;\n privateValueGen?: (val: any, key: string, item: T) => any;\n }\n) => {\n const {\n showPrivate,\n privacyMask,\n privateValueGen = (_, key) => `<Redacted property \"${key}\">`,\n } = options;\n\n const resolvePrivateValue = (key: string, val: any) => {\n // Allow to set custom \"redacted\" value by calling\n // `setCustomPrivateValue` from inside the filter function.\n let customPrivateValue;\n let setCustomPrivateValueCalled = false;\n const setCustomPrivateValue = (val: any) => {\n customPrivateValue = val;\n setCustomPrivateValueCalled = true;\n };\n\n const privacyFilter = privacyMask[key] as PrivacyFilter<any, any, any> | undefined;\n const isPrivate = privacyFilter\n ? privacyFilter(val, key, item, { setCustomPrivateValue, privateValueGen })\n : false;\n\n // prettier-ignore\n const privateValue = (\n // Don't redact anything if we're asked to show private data\n showPrivate ? val\n // Otherwise, if custom value was given, use that\n : setCustomPrivateValueCalled ? customPrivateValue\n // Otherwise, decide based on filter truthiness\n : isPrivate ? privateValueGen(val, key, item) : val\n );\n return privateValue;\n };\n\n const redactedObj = Object.entries(item).reduce((agg, [key, val]) => {\n const isNestedObj =\n typeof val === 'object' && val != null && !(val instanceof Date) && !Array.isArray(val);\n\n if (isNestedObj) {\n // Recursively process nested objects\n const subObj = applyPrivacyMask(val, {\n showPrivate,\n privacyMask: (privacyMask[key] ?? {}) as any,\n privateValueGen,\n });\n agg[key as keyof T] = subObj as any;\n } else {\n agg[key as keyof T] = resolvePrivateValue(key, val);\n }\n return agg;\n }, {} as T);\n\n return redactedObj;\n};\n\n/** Rename object properties in place */\nconst renameKeys = <T extends object>(item: T, keyNameMap: Partial<Record<keyof T, string>>) => {\n Object.entries(keyNameMap || {}).forEach(([oldPath, newPath]) => {\n if (oldPath === newPath) return;\n const val = get(item, oldPath);\n set(item, newPath as string, val);\n unset(item, oldPath);\n });\n return item;\n};\n\nconst sortObjectKeys = <T extends object>(obj: T) =>\n fromPairs(sortBy(Object.keys(obj)).map((key) => [key, obj[key]]));\n\n/**\n * Serialize dataset item to fixed-length hash.\n *\n * NOTE: Apify allows the key-value store key to be max 256 char long.\n * https://docs.apify.com/sdk/js/reference/class/KeyValueStore#setValue\n */\nexport const itemCacheKey = (item: any, primaryKeys?: string[]) => {\n const thePrimaryKeys = primaryKeys\n ? sortBy(uniq(primaryKeys.map((s) => s?.trim()).filter(Boolean)))\n : null;\n\n const serializedItem = thePrimaryKeys\n ? thePrimaryKeys.map((k) => item?.[k]).join(':')\n : item && isPlainObject(item)\n ? JSON.stringify(sortObjectKeys(item)) // If possible sort the object's keys\n : JSON.stringify(item);\n\n const cacheId = cyrb53(serializedItem);\n return cacheId.toString();\n};\n\n/**\n * Hashing function used when calculating cache ID hash from entries.\n *\n * See https://stackoverflow.com/a/52171480/9788634.\n */\nconst cyrb53 = (str, seed = 0) => {\n let h1 = 0xdeadbeef ^ seed,\n h2 = 0x41c6ce57 ^ seed;\n for (let i = 0, ch; i < str.length; i++) {\n ch = str.charCodeAt(i);\n h1 = Math.imul(h1 ^ ch, 2654435761);\n h2 = Math.imul(h2 ^ ch, 1597334677);\n }\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);\n h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);\n h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\n return 4294967296 * (2097151 & h2) + (h1 >>> 0);\n};\n\n/**\n * `Actor.pushData` with extra features:\n *\n * - (Optionally) Add metadata to entries before they are pushed to dataset.\n * - (Optionally) Set which (nested) properties are personal data and allow to\n * redact them for privacy compliance.\n */\nexport const pushData = async <\n Ctx extends CrawlingContext,\n T extends Record<any, any> = Record<any, any>\n>(\n oneOrManyItems: T | T[],\n ctx: Ctx,\n options: PushDataOptions<T>\n) => {\n const {\n includeMetadata,\n showPrivate,\n privacyMask,\n remapKeys,\n pickKeys,\n transform,\n filter,\n datasetIdOrName,\n cacheStoreIdOrName,\n cachePrimaryKeys,\n cacheActionOnResult,\n } = options;\n\n const items = Array.isArray(oneOrManyItems) ? oneOrManyItems : [oneOrManyItems];\n\n ctx.log.debug(`Preparing entries before pushing ${items.length} items to dataset`); // prettier-ignore\n const addMetadataToData = createMetadataMapper(ctx);\n\n const adjustedItems = await items.reduce(async (aggPromise, item) => {\n const agg = await aggPromise;\n\n const itemWithMetadata = includeMetadata ? addMetadataToData(item) : item;\n const maskedItem = applyPrivacyMask(itemWithMetadata, {\n showPrivate,\n privacyMask,\n privateValueGen: (val, key) =>\n `<Redacted property \"${key}\". To include the actual value, toggle ON the Actor input option \"Include personal data\">`,\n });\n\n const pickedItem = pickKeys ? pick(maskedItem, pickKeys) : maskedItem;\n const renamedItem = remapKeys ? renameKeys(pickedItem, remapKeys) : pickedItem;\n const transformedItem = transform ? await transform(renamedItem) : renamedItem;\n const passedFilter = filter ? await filter(transformedItem) : true;\n\n if (passedFilter) agg.push(transformedItem);\n\n return agg;\n }, Promise.resolve([] as unknown[]));\n\n // Push entries to primary dataset\n ctx.log.info(`Pushing ${adjustedItems.length} entries to dataset`);\n const dataset = datasetIdOrName ? await Actor.openDataset(datasetIdOrName) : Actor;\n await dataset.pushData(adjustedItems);\n ctx.log.info(`Done pushing ${adjustedItems.length} entries to dataset`);\n\n // Update entries in cache\n if (cacheStoreIdOrName && cacheActionOnResult) {\n ctx.log.info(`Update ${adjustedItems.length} entries in cache`);\n const store = await Actor.openKeyValueStore(cacheStoreIdOrName);\n await serialAsyncMap(adjustedItems, async (item: any) => {\n const cacheId = itemCacheKey(item, cachePrimaryKeys);\n\n if (['add', 'overwrite'].includes(cacheActionOnResult)) {\n await store.setValue(cacheId, item);\n } else if (cacheActionOnResult === 'remove') {\n await store.setValue(cacheId, null);\n }\n });\n ctx.log.info(`Done updating ${adjustedItems.length} entries in cache`);\n }\n\n return adjustedItems;\n};\n"]}