diff --git a/.prettierrc.js b/.prettierrc.js index a9f675aef..44da64ece 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,4 +1,4 @@ -module.exports = { +export default { trailingComma: "all", proseWrap: "always", }; diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 11cf3d164..43b3ee3d3 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -21,13 +21,18 @@ Read more: ## v0.18.0 +- Now published as pure ESM, but worry not as unflagged require(ESM) is now + enabled by default in + [Node 20.19.0+](https://nodejs.org/pt-br/blog/release/v20.19.0), + [Node 22.12.0+](https://nodejs.org/en/blog/release/v22.12.0) and Node 24+ so + everything should continue to work as before. - Since Node 20 is EOL, Node 22 is now the minimum supported version, per our [requirements documentation](https://worker.graphile.org/docs/requirements). - `Runner` gains `[Symbol.asyncDispose]()` method, so you can `await using runner = await run(...)` and the worker will be released when you reach the end of the scope. (Primarily useful for tests.) - Maintenance work: upgrade to latest TypeScript, Jest, eliminate ts-node, fix - yargs, use erasable syntax only for type-stripping support, + yargs, use erasable syntax only for type-stripping support. - `LogLevel` export is now type only - a string union rather than a TypeScript const enum. diff --git a/__tests__/fixtures/blah.js b/__tests__/fixtures/blah.cjs similarity index 100% rename from __tests__/fixtures/blah.js rename to __tests__/fixtures/blah.cjs diff --git a/__tests__/fixtures/tasks/wouldyoulike.js b/__tests__/fixtures/tasks/wouldyoulike.cjs similarity index 71% rename from __tests__/fixtures/tasks/wouldyoulike.js rename to __tests__/fixtures/tasks/wouldyoulike.cjs index c24b15f05..fc47399d6 100644 --- a/__tests__/fixtures/tasks/wouldyoulike.js +++ b/__tests__/fixtures/tasks/wouldyoulike.cjs @@ -1,4 +1,4 @@ -const { rand } = require("../blah.js"); +const { rand } = require("../blah.cjs"); module.exports = (_payload, helpers) => { helpers.logger.debug(rand()); return "some sausages"; diff --git a/__tests__/fixtures/tasks/wouldyoulike_default.js b/__tests__/fixtures/tasks/wouldyoulike_default.cjs similarity index 100% rename from __tests__/fixtures/tasks/wouldyoulike_default.js rename to __tests__/fixtures/tasks/wouldyoulike_default.cjs diff --git a/__tests__/fixtures/tasks/wouldyoulike_ts.js b/__tests__/fixtures/tasks/wouldyoulike_ts.cjs similarity index 83% rename from __tests__/fixtures/tasks/wouldyoulike_ts.js rename to __tests__/fixtures/tasks/wouldyoulike_ts.cjs index 6d961f637..586ca099a 100644 --- a/__tests__/fixtures/tasks/wouldyoulike_ts.js +++ b/__tests__/fixtures/tasks/wouldyoulike_ts.cjs @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const blah_1 = require("../blah.js"); +const blah_1 = require("../blah.cjs"); exports.default = (_payload, helpers) => { helpers.logger.debug((0, blah_1.rand)()); return "some TS sausages"; diff --git a/__tests__/fixtures/tasksFile-ts.js b/__tests__/fixtures/tasksFile-ts.cjs similarity index 100% rename from __tests__/fixtures/tasksFile-ts.js rename to __tests__/fixtures/tasksFile-ts.cjs diff --git a/__tests__/fixtures/tasksFile.js b/__tests__/fixtures/tasksFile.cjs similarity index 100% rename from __tests__/fixtures/tasksFile.js rename to __tests__/fixtures/tasksFile.cjs diff --git a/__tests__/fixtures/tasksFile_default-ts.js b/__tests__/fixtures/tasksFile_default-ts.cjs similarity index 100% rename from __tests__/fixtures/tasksFile_default-ts.js rename to __tests__/fixtures/tasksFile_default-ts.cjs diff --git a/__tests__/fixtures/tasksFile_default.js b/__tests__/fixtures/tasksFile_default.cjs similarity index 100% rename from __tests__/fixtures/tasksFile_default.js rename to __tests__/fixtures/tasksFile_default.cjs diff --git a/__tests__/getTasks.test.ts b/__tests__/getTasks.test.ts index f06d1c68f..f5206f718 100644 --- a/__tests__/getTasks.test.ts +++ b/__tests__/getTasks.test.ts @@ -8,6 +8,8 @@ import type { import { makeEnhancedWithPgClient } from "../src/lib.ts"; import { makeMockJob, withPgClient } from "./helpers.ts"; +const __dirname = import.meta.dirname; + const options: WorkerSharedOptions = {}; const neverAbortController = new AbortController(); @@ -58,7 +60,7 @@ describe("commonjs", () => { withPgClient(async (client) => { const { tasks, release, compiledSharedOptions } = (await getTasks( options, - `${__dirname}/fixtures/tasksFile.js`, + `${__dirname}/fixtures/tasksFile.cjs`, )) as WatchedTaskList & { compiledSharedOptions: CompiledSharedOptions }; expect(tasks).toBeTruthy(); expect(Object.keys(tasks).sort()).toMatchInlineSnapshot(` @@ -89,7 +91,7 @@ describe("commonjs", () => { withPgClient(async (client) => { const { tasks, release, compiledSharedOptions } = (await getTasks( options, - `${__dirname}/fixtures/tasksFile-ts.js`, + `${__dirname}/fixtures/tasksFile-ts.cjs`, )) as WatchedTaskList & { compiledSharedOptions: CompiledSharedOptions }; expect(tasks).toBeTruthy(); expect(Object.keys(tasks).sort()).toMatchInlineSnapshot(` @@ -122,7 +124,7 @@ describe("commonjs", () => { withPgClient(async (client) => { const { tasks, release, compiledSharedOptions } = (await getTasks( options, - `${__dirname}/fixtures/tasksFile_default.js`, + `${__dirname}/fixtures/tasksFile_default.cjs`, )) as WatchedTaskList & { compiledSharedOptions: CompiledSharedOptions }; expect(tasks).toBeTruthy(); expect(Object.keys(tasks).sort()).toMatchInlineSnapshot(` @@ -153,7 +155,7 @@ describe("commonjs", () => { withPgClient(async (client) => { const { tasks, release, compiledSharedOptions } = (await getTasks( options, - `${__dirname}/fixtures/tasksFile_default-ts.js`, + `${__dirname}/fixtures/tasksFile_default-ts.cjs`, )) as WatchedTaskList & { compiledSharedOptions: CompiledSharedOptions }; expect(tasks).toBeTruthy(); expect(Object.keys(tasks).sort()).toMatchInlineSnapshot(` diff --git a/eslint.config.js b/eslint.config.js index 897e300ee..cb9c313c5 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,7 +1,8 @@ -const js = require("@eslint/js"); -const { FlatCompat } = require("@eslint/eslintrc"); -const { readFileSync } = require("node:fs"); +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; +import { readFileSync } from "node:fs"; +const __dirname = import.meta.dirname; const compat = new FlatCompat({ baseDirectory: __dirname, recommendedConfig: js.configs.recommended, @@ -22,7 +23,7 @@ const ignores = readFileSync(`${__dirname}/.lintignore`, "utf8") }) .filter((l) => l != null); -module.exports = [ +export default [ { ignores: [...ignores, "eslint.config.js", ".prettierrc.js"], }, @@ -162,6 +163,7 @@ module.exports = [ files: ["perfTest/**/*", "examples/**/*"], rules: { "import-x/extensions": "off", + "import-x/no-unresolved": "off", "@typescript-eslint/no-var-requires": 0, }, }, diff --git a/examples/readme/events.js b/examples/readme/events.js index e2e4b1a9a..de98080ce 100644 --- a/examples/readme/events.js +++ b/examples/readme/events.js @@ -1,6 +1,4 @@ -const { run, addJobAdhoc } = require( - /* "graphile-worker" */ "../../dist/index.js", -); +import { addJobAdhoc, run } from /* "graphile-worker" */ "../../dist/index.js"; async function main() { // Run a worker to execute jobs: diff --git a/examples/readme/tasks/task_2.js b/examples/readme/tasks/task_2.js index ee64cdb4a..c02b97d2c 100644 --- a/examples/readme/tasks/task_2.js +++ b/examples/readme/tasks/task_2.js @@ -1,4 +1,4 @@ -module.exports = async (payload, helpers) => { +export default async function task2(payload, helpers) { // async is optional, but best practice helpers.logger.debug(`Received ${JSON.stringify(payload)}`); -}; +} diff --git a/examples/worker-bullmq-exporter/tasks/bullmq-exporter.js b/examples/worker-bullmq-exporter/tasks/bullmq-exporter.js index 4475c78e2..ff8b328a0 100644 --- a/examples/worker-bullmq-exporter/tasks/bullmq-exporter.js +++ b/examples/worker-bullmq-exporter/tasks/bullmq-exporter.js @@ -1,4 +1,4 @@ -const { Queue } = require("bullmq"); +import { Queue } from "bullmq"; const defaultQueueName = "database-events"; const queueName = process.env.QUEUE_NAME || defaultQueueName; diff --git a/examples/worker-cloud-tasks-exporter/README.md b/examples/worker-cloud-tasks-exporter/README.md index b20dab492..b2eb0279a 100644 --- a/examples/worker-cloud-tasks-exporter/README.md +++ b/examples/worker-cloud-tasks-exporter/README.md @@ -47,7 +47,7 @@ To create tasks in Cloud Tasks ```js // tasks/cloud-tasks-exporter.js -const { CloudTasksClient } = require("@google-cloud/tasks"); +import { CloudTasksClient } from "@google-cloud/tasks"; const client = new CloudTasksClient(); @@ -110,7 +110,7 @@ To run Graphile Worker task ```js // tasks/cloud-tasks-exporter.js -module.exports = async (payload, { logger }) => { +export default async function task(payload, { logger }) { logger.info( `Delegating task to Cloud Tasks with payload ${JSON.stringify(payload)}`, ); @@ -122,7 +122,7 @@ module.exports = async (payload, { logger }) => { }); logger.info("Done!"); -}; +} ``` ## Run the worker and add a job diff --git a/examples/worker-cloud-tasks-exporter/tasks/cloud-tasks-exporter.js b/examples/worker-cloud-tasks-exporter/tasks/cloud-tasks-exporter.js index 51a13ff40..08c59acf3 100644 --- a/examples/worker-cloud-tasks-exporter/tasks/cloud-tasks-exporter.js +++ b/examples/worker-cloud-tasks-exporter/tasks/cloud-tasks-exporter.js @@ -1,4 +1,4 @@ -const { CloudTasksClient } = require("@google-cloud/tasks"); +import { CloudTasksClient } from "@google-cloud/tasks"; const client = new CloudTasksClient(); @@ -56,7 +56,7 @@ async function createTask({ } // Graphile Worker Task -module.exports = async (payload, { logger }) => { +export default async function cloudTasksExporter(payload, { logger }) { logger.info( `Delegating task to Cloud Tasks with payload ${JSON.stringify(payload)}`, ); @@ -68,4 +68,4 @@ module.exports = async (payload, { logger }) => { }); logger.info("Done!"); -}; +} diff --git a/examples/worker-faktory-exporter/README.md b/examples/worker-faktory-exporter/README.md index b58b04044..7cc25930a 100644 --- a/examples/worker-faktory-exporter/README.md +++ b/examples/worker-faktory-exporter/README.md @@ -22,9 +22,9 @@ job from a queue. ```JS // tasks/faktory-export.js -const faktory = require("faktory-worker"); +import faktory from "faktory-worker"; -module.exports = async (payload, helpers) => { +export default async function task(payload, helpers) { const { param } = payload; const { logger } = helpers; diff --git a/examples/worker-faktory-exporter/tasks/faktory-exporter.js b/examples/worker-faktory-exporter/tasks/faktory-exporter.js index 331204e77..5bd2661d7 100644 --- a/examples/worker-faktory-exporter/tasks/faktory-exporter.js +++ b/examples/worker-faktory-exporter/tasks/faktory-exporter.js @@ -1,6 +1,6 @@ -const faktory = require("faktory-worker"); +import faktory from "faktory-worker"; -module.exports = async (payload, helpers) => { +export default async function faktoryExporter(payload, helpers) { const { param } = payload; const { logger } = helpers; @@ -17,4 +17,4 @@ module.exports = async (payload, helpers) => { logger.info(`Received jid from Faktory: ${jid}. Thanks Faktory!`); await faktoryClient.close(); -}; +} diff --git a/jest.config.js b/jest.config.cjs similarity index 91% rename from jest.config.js rename to jest.config.cjs index d004e069b..b1f37b9a3 100644 --- a/jest.config.js +++ b/jest.config.cjs @@ -8,7 +8,7 @@ module.exports = { }, testRegex: "(/__tests__/.*\\.(test|spec))\\.[tj]sx?$", moduleFileExtensions: ["ts", "mjs", "js", "json"], - extensionsToTreatAsEsm: [], + extensionsToTreatAsEsm: [".ts"], moduleNameMapper: { "^(\\.{1,2}/.*)\\.js$": "$1", }, diff --git a/package.json b/package.json index 22b324887..cf7f71147 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "graphile-worker", "version": "0.17.2", - "type": "commonjs", + "type": "module", "description": "Job queue for PostgreSQL", "main": "dist/index.js", "scripts": { diff --git a/scripts/options.mjs b/scripts/options.mjs index 969b747e2..4b8396dff 100755 --- a/scripts/options.mjs +++ b/scripts/options.mjs @@ -4,16 +4,51 @@ import "zx/globals"; import * as fs from "fs/promises"; -await $`yarn link`; - // Create a temporary instance so we can read the options const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "gwdu-")); const prev = process.cwd(); + +// Determine TypeScript version to synchronise with ours +const packageJson = JSON.parse( + await fs.readFile(`${prev}/package.json`, "utf8"), +); +const typescriptVersion = packageJson.devDependencies.typescript; +if (!typescriptVersion) { + throw new Error("Could not determine `typescript` version"); +} +const graphileVersion = packageJson.devDependencies.graphile; +if (!graphileVersion) { + throw new Error("Could not determine `graphile` version"); +} + +await fs.writeFile( + `${tmp}/package.json`, + JSON.stringify( + { type: "module", name: "@localrepo/tmp", private: true }, + null, + 2, + ) + "\n", +); +await fs.cp(`${prev}/.yarnrc.yml`, `${tmp}/.yarnrc.yml`); +await fs.cp(`${prev}/.yarn`, `${tmp}/.yarn/`, { recursive: true }); cd(tmp); -await $`yarn link graphile-worker`; -await $`yarn add typescript graphile`; +await $`yarn link ${prev}`; + +// If we have the crystal repo locally, use it's version of the `graphile` CLI +try { + const crystalRepo = `${process.env.HOME}/Dev/graphile/crystal`; + const stat = await fs.stat(crystalRepo); + if (stat.isDirectory()) { + console.log(`Using local crystal modules`); + await $`yarn link ${crystalRepo} --all`; + } +} catch { + // Ignore +} + +await $`yarn add graphile-worker graphile@${graphileVersion} typescript@${typescriptVersion}`; await fs.writeFile( - `graphile.config.mts`, + `graphile.config.ts`, `\ import type {} from "graphile-worker"; @@ -26,7 +61,7 @@ export default preset; ); // Get the markdown output for options -const output = await $`graphile config options`; +const output = await $`yarn graphile config options`; // Go back and destroy our tempdir cd(prev); @@ -37,6 +72,7 @@ await fs.rm(tmp, { recursive: true, force: true }); const SEARCH = "\n## worker\n"; const i = output.stdout.indexOf(SEARCH); if (i < 0) { + console.log(output.stdout); throw new Error("Worker heading not found!"); } const optionsMd = output.stdout diff --git a/src/cli.ts b/src/cli.ts index 3a3b3bfcb..876437e88 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node import { loadConfig } from "graphile-config/load"; -import * as yargs from "yargs"; +import yargs from "yargs"; import { assertCleanupTasks, cleanup } from "./cleanup.ts"; import { getCronItemsInternal } from "./getCronItems.ts"; @@ -9,7 +9,7 @@ import { getUtilsAndReleasersFromOptions } from "./lib.ts"; import { EMPTY_PRESET, WorkerPreset } from "./preset.ts"; import { runInternal, runOnceInternal } from "./runner.ts"; -const argv = yargs +const argv = yargs(process.argv.slice(2)) .parserConfiguration({ "boolean-negation": false, }) diff --git a/website/docs/cli/index.md b/website/docs/cli/index.md index 62154b15c..7854408a2 100644 --- a/website/docs/cli/index.md +++ b/website/docs/cli/index.md @@ -24,10 +24,10 @@ Create a `tasks/` folder, and place in it JS files containing your task specs. The names of these files will be the task identifiers, e.g. `hello` below: ```js title="tasks/hello.js" -module.exports = async (payload, helpers) => { +export default async function hello(payload, helpers) { const { name } = payload; helpers.logger.info(`Hello, ${name}`); -}; +} ``` ### Run the worker diff --git a/website/docs/config.md b/website/docs/config.md index 03420ecb9..d32cb5e13 100644 --- a/website/docs/config.md +++ b/website/docs/config.md @@ -28,10 +28,10 @@ We therefore recommend that the preset be the default export of a Here's an example in JavaScript: -```ts title="graphile.config.js" -const { WorkerPreset } = require("graphile-worker"); +```js title="graphile.config.js" +import { WorkerPreset } from "graphile-worker"; -module.exports = { +export default { extends: [WorkerPreset], worker: { connectionString: process.env.DATABASE_URL, @@ -173,11 +173,11 @@ Options for Graphile Worker size: number; ttl?: number; refetchDelay?: { - durationMs: number; - threshold?: number; - maxAbortThreshold?: number; + durationMs: number; + threshold?: number; + maxAbortThreshold?: number; }; -}; + }; logger?: Logger<{}>; maxPoolSize?: number; maxResetLockedInterval?: number; @@ -208,19 +208,22 @@ crash or kill) may result in the jobs being executed again once they expire ### worker.concurrentJobs -Type: `number | undefined` +Type: `number | undefined` +Default value: `1` Number of jobs to run concurrently on a single Graphile Worker instance. ### worker.connectionString -Type: `string | undefined` +Type: `string | undefined` +Default value: `process.env.DATABASE_URL` Database [connection string](/docs/connection-string). ### worker.crontabFile -Type: `string | undefined` +Type: `string | undefined` +Default value: `process.cwd() + "/crontab"` The path to a file in which Graphile Worker should look for crontab schedules. See: [recurring tasks (crontab)](/docs/cron)). @@ -248,7 +251,8 @@ failure. ### worker.fileExtensions -Type: `string[] | undefined` +Type: `string[] | undefined` +Default value: `[".js", ".cjs", ".mjs"]` A list of file extensions (in priority order) that Graphile Worker should attempt to import as Node modules when loading task executors from the file @@ -256,7 +260,8 @@ system. ### worker.getQueueNameBatchDelay -Type: `number | undefined` +Type: `number | undefined` +Default value: `50` **Experimental** @@ -266,7 +271,8 @@ window for greater efficiency, or reduce it to improve latency. ### worker.gracefulShutdownAbortTimeout -Type: `number | undefined` +Type: `number | undefined` +Default value: `5_000` How long in milliseconds after a gracefulShutdown is triggered should Graphile Worker wait to trigger the AbortController, which should cancel supported @@ -275,7 +281,18 @@ asynchronous actions? ### worker.localQueue Type: -`{ size: number; ttl?: number; refetchDelay?: { durationMs: number; threshold?: number; maxAbortThreshold?: number; }; } | undefined` + +```ts +{ + size: number; + ttl?: number; + refetchDelay?: { + durationMs: number; + threshold?: number; + maxAbortThreshold?: number; + }; +} | undefined +``` The localQueue enables Graphile Worker to lock and pull down a batch of jobs to execute at once, distributing them to individual workers on demand without the @@ -299,7 +316,8 @@ A Logger instance (see [Logger](/docs/library/logger)). ### worker.maxPoolSize -Type: `number | undefined` +Type: `number | undefined` +Default value: `10` Maximum number of concurrent connections to Postgres; must be at least `2`. This number can be lower than `concurrentJobs`, however a low pool size may cause @@ -311,7 +329,8 @@ your logic.) ### worker.maxResetLockedInterval -Type: `number | undefined` +Type: `number | undefined` +Default value: `600_000` **Experimental** @@ -320,7 +339,8 @@ scans for jobs that have been locked too long (see `minResetLockedInterval`). ### worker.minResetLockedInterval -Type: `number | undefined` +Type: `number | undefined` +Default value: `480_000` **Experimental** @@ -330,31 +350,36 @@ choose a time between this and `maxResetLockedInterval`. ### worker.pollInterval -Type: `number | undefined` +Type: `number | undefined` +Default value: `2000` ### worker.preparedStatements -Type: `boolean | undefined` +Type: `boolean | undefined` +Default value: `true` Whether Graphile Worker should use prepared statements. Set `false` if you use software (e.g. some Postgres pools) that don't support them. ### worker.schema -Type: `string | undefined` +Type: `string | undefined` +Default value: `graphile_worker` The database schema in which Graphile Worker's tables, functions, views, etc are located. Graphile Worker will create or edit things in this schema as necessary. ### worker.taskDirectory -Type: `string | undefined` +Type: `string | undefined` +Default value: `process.cwd() + "/tasks"` The path to a directory in which Graphile Worker should look for task executors. ### worker.useNodeTime -Type: `boolean | undefined` +Type: `boolean | undefined` +Default value: `false` Set to `true` to use the time as recorded by Node.js rather than PostgreSQL. It's strongly recommended that you ensure the Node.js and PostgreSQL times are diff --git a/website/docs/contributing.md b/website/docs/contributing.md index 88ac8208f..8dca6d7fa 100644 --- a/website/docs/contributing.md +++ b/website/docs/contributing.md @@ -95,7 +95,7 @@ you should create a tasks folder first (but not in the root!): ```sh yarn prepack mkdir -p _LOCAL/tasks -echo 'module.exports = () => {}' > _LOCAL/tasks/hello.js +echo 'export default function hello() {}' > _LOCAL/tasks/hello.js cd _LOCAL node ../dist/cli.js -c "postgres:///my_db" ``` diff --git a/website/docs/library/index.md b/website/docs/library/index.md index 97c189e3c..8db387e85 100644 --- a/website/docs/library/index.md +++ b/website/docs/library/index.md @@ -26,7 +26,7 @@ The following is equivalent to the setup in [the CLI quickstart](/docs/cli#quickstart): ```js -const { run } = require("graphile-worker"); +import { run } from "graphile-worker"; async function main() { // Run a worker to execute jobs: @@ -62,12 +62,20 @@ main().catch((err) => { }); ``` +:::tip CommonJS + +Graphile Worker is published as ESM, but the minimum supported Node.js version +supports `require(esm)`. If your application is still CommonJS, you may continue +to load the library with `const { run } = require("graphile-worker")`. + +::: + ### Add a job via the library You can also use the library to quickly add a job: ```js -const { addJobAdhoc } = require("graphile-worker"); +import { addJobAdhoc } from "graphile-worker"; addJobAdhoc( // makeWorkerUtils options diff --git a/website/docs/library/logger.md b/website/docs/library/logger.md index e8b5953df..672931973 100644 --- a/website/docs/library/logger.md +++ b/website/docs/library/logger.md @@ -24,7 +24,7 @@ You may customize where log messages from `graphile-worker` (and your tasks) go by supplying a custom `Logger` instance using your own `logFactory`. ```js -const { Logger, run } = require("graphile-worker"); +import { Logger, run } from "graphile-worker"; /* Replace this function with your own implementation */ function logFactory(scope) { diff --git a/website/docs/library/queue.md b/website/docs/library/queue.md index c1e12fd6f..e81edef13 100644 --- a/website/docs/library/queue.md +++ b/website/docs/library/queue.md @@ -33,7 +33,7 @@ Useful for adding jobs from within JavaScript in an efficient way. Runnable example: ```js -const { makeWorkerUtils } = require("graphile-worker"); +import { makeWorkerUtils } from "graphile-worker"; async function main() { const workerUtils = await makeWorkerUtils({ @@ -143,7 +143,7 @@ one-off scripts this convenience method may be enough. Runnable example: ```js -const { addJobAdhoc } = require("graphile-worker"); +import { addJobAdhoc } from "graphile-worker"; async function main() { await addJobAdhoc( diff --git a/website/docs/requirements.md b/website/docs/requirements.md index 91ed1c98a..865bbe74e 100644 --- a/website/docs/requirements.md +++ b/website/docs/requirements.md @@ -3,18 +3,13 @@ title: Requirements sidebar_position: 30 --- -The current version of Graphile Worker requires PostgreSQL 12+ and Node 18+[^1]. +The current version of Graphile Worker requires PostgreSQL 12+ and Node 22.18+. Once a version of PostgreSQL or Node.js reaches end of life, we also no longer support it and may drop support in a minor update. Should you require support for an end-of-life version of one of these projects, please [get in touch about our commercial support options](https://graphile.org/support/). -[^1]: - Might work with older versions, but has not been tested. Node 18 won't run - our jest tests due to segfault, fixed in Node 20.8.1, so CI cannot run - against Node 18. - :::note `graphile-worker` versions before 0.13.0 installed the `pgcrypto` extension into diff --git a/website/docs/tasks.md b/website/docs/tasks.md index 4408f849a..9138eca91 100644 --- a/website/docs/tasks.md +++ b/website/docs/tasks.md @@ -54,16 +54,16 @@ extra side effects) — for example sending emails. ## Example JS task executors ```js title="tasks/task_1.js" -module.exports = async (payload) => { +export default async function task1(payload) { await doMyLogicWith(payload); -}; +} ``` ```js title="tasks/task_2.js" -module.exports = async (payload, helpers) => { +export default async function task2(payload, helpers) { // async is optional, but best practice helpers.logger.debug(`Received ${JSON.stringify(payload)}`); -}; +} ``` ## The task directory