{"id":21223074,"url":"https://github.com/nestdotland/hatcher","last_synced_at":"2025-07-29T17:14:21.778Z","repository":{"id":49582465,"uuid":"279316265","full_name":"nestdotland/hatcher","owner":"nestdotland","description":"🐣 Registries toolbox \u0026 update notifications for your CLI","archived":false,"fork":false,"pushed_at":"2021-07-04T20:23:27.000Z","size":165,"stargazers_count":14,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-09T21:58:09.018Z","etag":null,"topics":["deno","nestland"],"latest_commit_sha":null,"homepage":"https://nest.land/package/hatcher","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nestdotland.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-13T13:52:11.000Z","updated_at":"2021-09-26T02:55:50.000Z","dependencies_parsed_at":"2022-08-30T20:22:33.715Z","dependency_job_id":null,"html_url":"https://github.com/nestdotland/hatcher","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/nestdotland/hatcher","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nestdotland%2Fhatcher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nestdotland%2Fhatcher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nestdotland%2Fhatcher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nestdotland%2Fhatcher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nestdotland","download_url":"https://codeload.github.com/nestdotland/hatcher/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nestdotland%2Fhatcher/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265809599,"owners_count":23831929,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","nestland"],"created_at":"2024-11-20T22:48:43.386Z","updated_at":"2025-07-29T17:14:21.745Z","avatar_url":"https://github.com/nestdotland.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/nestdotland/nest.land\"\u003e\n    \u003cimg\n       src=\"https://raw.githubusercontent.com/nestdotland/hatcher/master/img/hatcher_light_bck.svg\"\n       alt=\"logo\"\n       width=\"110\"\n    \u003e\n  \u003c/a\u003e\n\n\u003ch3 align=\"center\"\u003eHatcher\u003c/h3\u003e\n\u003cp align=\"center\"\u003e\n    Registries toolbox \u0026 update notifications for your CLI\n  \u003c/p\u003e\n  \u003cp align=\"center\"\u003e\n    \u003ca href=\"https://nest.land/package/hatcher\"\u003e\n      \u003cimg src=\"https://nest.land/badge.svg\" alt=\"nest.land badge\"\u003e\n    \u003c/a\u003e\n    \u003cimg\n      src=\"https://github.com/nestdotland/hatcher/workflows/Lint/badge.svg\"\n      alt=\"Eggs lint\"\n    \u003e\n    \u003cimg\n      src=\"https://github.com/nestdotland/hatcher/workflows/Test/badge.svg\"\n      alt=\"Eggs test\"\n    \u003e\n    \u003cimg\n      src=\"https://github.com/nestdotland/hatcher/workflows/Ship/badge.svg\"\n      alt=\"Eggs ship\"\n    \u003e\n    \u003ca href=\"https://discord.gg/hYUsX3H\"\u003e\n      \u003cimg\n        src=\"https://img.shields.io/discord/722823139960291328?label=Discord\u0026logo=discord\"\n        alt=\"Discord\"\n      \u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n![notification](./img/notification.png)\n\n\u003e Inspired by the node package\n\u003e [update-notifier](https://github.com/yeoman/update-notifier).\n\n# Contents\n\n- [Contents](#contents)\n- [Usage](#usage)\n  - [Update Notifier](#update-notifier)\n    - [Simple](#simple)\n    - [Comprehensive](#comprehensive)\n    - [Adding update notification to any CLI](#adding-update-notification-to-any-cli)\n    - [How](#how)\n  - [Registries toolbox](#registries-toolbox)\n- [API](#api)\n  - [notifier = UpdateNotifier({ name, owner, registry, currentVersion,\n    updateCheckInterval})](#notifier--updatenotifier-name-owner-registry-currentversion-updatecheckinterval)\n    - [name](#name)\n    - [owner](#owner)\n    - [registry](#registry)\n    - [currentVersion](#currentversion)\n    - [updateCheckInterval](#updatecheckinterval)\n  - [notifier.checkForUpdates(configDir)](#notifiercheckforupdatesconfigdir)\n  - [notifier.notify(command, overwrite)](#notifiernotifycommand-overwrite)\n    - [command](#command)\n    - [overwrite](#overwrite)\n    - [Custom message](#custom-message)\n  - [Update](#update)\n  - [Registry Class](#registry-class)\n  - [latestVersion(registryDomain, module,\n    owner)](#latestversionregistrydomain-module-owner)\n    - [registryDomain](#registrydomain)\n    - [module](#module)\n    - [owner](#owner-1)\n    - [return type](#return-type)\n  - [latestStableVersion(registryDomain, module,\n    owner)](#lateststableversionregistrydomain-module-owner)\n  - [sortedVersions(registryDomain, module,\n    owner)](#sortedversionsregistrydomain-module-owner)\n    - [registryDomain](#registrydomain-1)\n    - [module](#module-1)\n    - [owner](#owner-2)\n    - [return type](#return-type-1)\n  - [parseURL(url)](#parseurlurl)\n    - [url](#url)\n    - [return type](#return-type-2)\n  - [getRegistry(registryDomain)](#getregistryregistrydomain)\n    - [registryDomain](#registrydomain-2)\n    - [return type](#return-type-3)\n- [Contributing](#contributing)\n\n# Usage\n\n## Update Notifier\n\n### Simple\n\n```ts\nimport {\n  NestLand,\n  UpdateNotifier,\n} from \"https://x.nest.land/hatcher@0.9.2/mod.ts\";\n\nconst notifier = new UpdateNotifier({\n  name: \"denon\",\n  registry: NestLand,\n  currentVersion: \"0.1.2\",\n});\n\nawait notifier.checkForUpdates();\nnotifier.notify();\n```\n\n### Comprehensive\n\n```ts\nimport {\n  Github,\n  UpdateNotifier,\n} from \"https://x.nest.land/hatcher@0.9.2/mod.ts\";\n\nconst notifier = new UpdateNotifier({\n  name: \"denon\", // module name\n  owner: \"denosaurs\", // module owner, mandatory for registries like github\n  registry: Github, // registry object\n  currentVersion: \"0.1.2\",\n  updateCheckInterval: 1000 * 60 * 60, // time interval between two checks, in milliseconds\n});\n\nconst update = await notifier.checkForUpdates(); // undefined if there is no update available\nconsole.log(update);\n/** {\n  current: \"0.1.2\",\n  latest: \"2.4.0\",\n  type: \"major\",\n  name: \"denon\",\n  owner: \"denosaurs\",\n  registry: \"raw.githubusercontent.com\"\n} */\n\nnotifier.notify(\"my command\"); // displays the default notification with a custom command\n```\n\n![comprehensive](img/comprehensive.png)\n\n### Adding update notification to any CLI\n\nSuppose denon does not use hatcher to notify its users of updates.\n\n**You can install denon with hatcher built-in !**\n\nIf the install command is :\n\n```sh\ndeno install --allow-read --allow-run --allow-write --allow-net -f -q --unstable https://deno.land/x/denon@2.4.0/denon.ts\n```\n\nYou can do:\n\n```sh\ndeno install -A https://x.nest.land/hatcher@0.9.2/hatcher.ts\nhatcher --allow-read --allow-run --allow-write --allow-net -f -q --unstable https://deno.land/x/denon@2.4.0/denon.ts\n```\n\nAnd voila ! You will be notified as soon as an update is available.\n\n### How\n\nWhenever you initiate the update notifier and it's not within the interval\nthreshold, it will asynchronously check with the specified registry for\navailable updates, then persist the result. This prevents any impact on your\nmodule startup performance.\n\nThe first time the user runs your app, it will check for an update, and even if\nan update is available, it will wait the specified updateCheckInterval before\nnotifying the user (one day by default). This is done to not be annoying to the\nuser, but might surprise you as an implementer if you're testing whether it\nworks. Check out example.ts to quickly test out hatcher and see how you can test\nthat it works in your app.\n\n```sh\ndeno run -A https://x.nest.land/hatcher@0.9.2/example.ts\n```\n\n## Registries toolbox\n\n```ts\nimport {\n  getLatestVersion,\n  parseURL,\n} from \"https://x.nest.land/hatcher@0.9.2/mod.ts\";\n\nconst result = parseURL(\"https://deno.land/x/denon@1.2.0/src/runner.ts\");\n/** {\n  registry: \"deno.land\",\n  name: \"denon\",\n  version: \"1.2.0\",\n  parsedURL: \"https://deno.land/x/denon@${version}/src/runner.ts\",\n  relativePath: \"src/runner.ts\",\n  owner: \"\"\n} */\n\nconst latestVersion = await getLatestVersion(\"deno.land\", \"denon\");\nconsole.log(latestVersion); // 0.2.4\n```\n\n# API\n\n## notifier = UpdateNotifier({ name, owner, registry, currentVersion, updateCheckInterval})\n\n### name\n\n_required_\n\ntype: `string`\n\n### owner\n\n_required for raw.githubusercontent.com, denopkg.com_\n\ntype: `string`\n\n### registry\n\n_required_\n\ntype: [`Registry`](#registry-class)\n\n### currentVersion\n\n_required_\n\ntype: `string | semver.SemVer`\n\n### updateCheckInterval\n\nIn milliseconds, defaults to one day.\n\ntype: `number`\n\n## notifier.checkForUpdates(configDir)\n\n`configDir` is the directory where hatcher will save some information about your\nmodule.\n\nDefaults to `~/.deno/hatcher`\n\nReturns an [`Update`](#update) object if there is an update available,\n`undefined` otherwise.\n\n## notifier.notify(command, overwrite)\n\nBy default, will ask the user to visit the registry.\n\n```ts\nnotifier.notify();\n```\n\n![default](img/default.png)\n\n### command\n\ntype: `string`\n\n```ts\nnotifier.notify(\"my command\");\n```\n\n![command](img/command.png)\n\n### overwrite\n\ntype: `boolean`\n\nWill overwrite the body of the notification.\n\n```ts\nnotifier.notify(\"My custom message\", true);\n```\n\n![overwrite](img/overwrite.png)\n\n### Custom message\n\nYou can of course also display a fully customized message if an\n[update](#update) is available.\n\n```ts\nconst update = await notifier.checkForUpdates();\nif (update) {\n  console.log(`New update! ${update.latest}`);\n}\n```\n\n## Update\n\n```ts\n{\n  latest:\n  string;\n  current:\n  string;\n  type:\n  semver.ReleaseType | null; // \"pre\" | \"major\" | \"premajor\" | \"minor\" | \"preminor\" | \"patch\" | \"prepatch\" | \"prerelease\" | null\n  name:\n  string;\n  owner:\n  string;\n  registry:\n  string;\n}\n```\n\n## Registry Class\n\nSupported registers for the time being:\n\n| domain (string)             | Registry class |\n| --------------------------- | -------------- |\n| `deno.land`                 | `DenoLand`     |\n| `denopkg.com`               | `Denopkg`      |\n| `raw.githubusercontent.com` | `Github`       |\n| `jspm.dev`                  | `Jspm`         |\n| `x.nest.land`               | `NestLand`     |\n| `cdn.skypack.dev`           | `Skypack`      |\n\nYou can add your own registers by adding them to `registries`.\n\n```ts\nimport { registries } from \"https://x.nest.land/hatcher@0.9.2/mod.ts\";\n\nregistries.push(myRegistry);\n```\n\nYour registry must implement the Registry object:\n\n```ts\nabstract class Registry {\n  static domain: string;\n\n  static async latestVersion(\n    module: string,\n    owner?: string,\n  ): Promise\u003cstring | undefined\u003e;\n\n  static async latestStableVersion(\n    module: string,\n    owner?: string,\n  ): Promise\u003cstring | undefined\u003e;\n\n  static async sortedVersions(\n    module: string,\n    owner?: string,\n  ): Promise\u003cstring[]\u003e;\n\n  static parseURL(url: string): URLData;\n}\n```\n\n## latestVersion(registryDomain, module, owner)\n\nGet latest version from supported registries\n\n### registryDomain\n\n_required_\n\ntype: `string`\n\nOne of the [supported registries](#registry-class) domain.\n\n### module\n\n_required_\n\ntype: `string`\n\n### owner\n\n_required for raw.githubusercontent.com, denopkg.com_\n\ntype: `string`\n\n### return type\n\ntype: `string`\n\n## latestStableVersion(registryDomain, module, owner)\n\nSame as `latestVersion` but get the latest stable version according to the\nSemVer rules.\n\n## sortedVersions(registryDomain, module, owner)\n\nGet sorted versions from supported registries\n\n### registryDomain\n\n_required_\n\ntype: `string`\n\nOne of the [supported registries](#registry-class) domain.\n\n### module\n\n_required_\n\ntype: `string`\n\n### owner\n\n_required for raw.githubusercontent.com, denopkg.com_\n\ntype: `string`\n\n### return type\n\ntype: `string[]`\n\n## parseURL(url)\n\nParse an URL from supported registries\n\n### url\n\n_required_\n\ntype: `string`\n\n### return type\n\n```ts\ninterface ProcessedURL {\n  registry: string;\n  name: string;\n  owner: string;\n  version: string;\n  parsedURL: string;\n  relativePath: string;\n}\n```\n\n## getRegistry(registryDomain)\n\nGet registry object from web domain\n\n### registryDomain\n\n_required_\n\ntype: `string`\n\n### return type\n\ntype: `Registry`\n\n# Contributing\n\n\u003cimg alt=\"GitHub Hacktoberfest combined status\" src=\"https://img.shields.io/github/hacktoberfest/2020/nestdotland/eggs?logo=digitalocean\"\u003e\n\nAll contributions are welcome! If you can think of a command or feature that\nmight benefit nest.land, fork this repository and make a pull request from your\nbranch with the additions. Make sure to use\n[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)\n\n[Contribution guide](.github/CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnestdotland%2Fhatcher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnestdotland%2Fhatcher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnestdotland%2Fhatcher/lists"}