{"id":24807282,"url":"https://github.com/stackpress/lib","last_synced_at":"2025-08-19T02:34:00.860Z","repository":{"id":259856311,"uuid":"879528789","full_name":"stackpress/lib","owner":"stackpress","description":"Common typescript types","archived":false,"fork":false,"pushed_at":"2025-01-21T07:26:13.000Z","size":146,"stargazers_count":0,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-21T07:27:39.749Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stackpress.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-28T04:35:02.000Z","updated_at":"2025-01-21T07:26:17.000Z","dependencies_parsed_at":"2024-12-02T09:26:48.141Z","dependency_job_id":"1d8f4773-20e5-464e-87ff-4a5dde94bd64","html_url":"https://github.com/stackpress/lib","commit_stats":null,"previous_names":["stackpress/types","stackpress/lib"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackpress%2Flib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackpress%2Flib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackpress%2Flib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackpress%2Flib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stackpress","download_url":"https://codeload.github.com/stackpress/lib/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236323453,"owners_count":19130635,"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":[],"created_at":"2025-01-30T09:18:01.599Z","updated_at":"2025-01-30T09:18:02.685Z","avatar_url":"https://github.com/stackpress.png","language":"TypeScript","readme":"# 📖 Stackpress Library\n\n[![NPM Package](https://img.shields.io/npm/v/@stackpress/lib.svg?style=flat)](https://www.npmjs.com/package/@stackpress/lib)\n[![Tests Status](https://img.shields.io/github/actions/workflow/status/stackpress/lib/test.yml)](https://github.com/stackpress/lib/actions)\n[![Coverage Status](https://coveralls.io/repos/github/stackpress/lib/badge.svg?branch=main)](https://coveralls.io/github/stackpress/lib?branch=main)\n[![Commits](https://img.shields.io/github/last-commit/stackpress/lib)](https://github.com/stackpress/lib/commits/main/)\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat)](https://github.com/stackpress/lib/blob/main/LICENSE)\n\nShared library used across Stackpress projects. Standardize type \ndefinitions across different projects and potentially save time for \ndevelopers who would otherwise need to define these common types \nthemselves.\n\n## Install\n\n```bash\n$ npm i @stackpress/lib\n```\n\n## Usage\n\n - [Data](#data)\n   - [Nest](#nest)\n   - [ReadonlyMap](#rmap)\n   - [ReadonlyNest](#rnest)\n   - [ReadonlySet](#rset)\n - [Event](#event)\n   - [EventEmitter](#emitter)\n   - [EventRouter](#router)\n   - [EventTerminal](#terminal)\n - [Queue](#queue)\n   - [ItemQueue](#item)\n   - [TaskQueue](#task)\n - [File System](#system)\n - [Exception](#exception)\n - [Reflection](#reflection)\n - [Status](#status)\n\n\u003ca name=\"data\"\u003e\u003c/a\u003e\n\n## Data\n\nThe data library helps with common data management scenarios.\n\n  - [Nest](#nest)\n  - [ReadonlyMap](#rmap)\n  - [ReadonlyNest](#rnest)\n  - [ReadonlySet](#rset)\n\n\u003ca name=\"nest\"\u003e\u003c/a\u003e\n\n### Nest\n\nA nest is a data object that contain other nested data objects or arrays. \n\n```js\nimport { Nest, UnknownNest } from '@stackpress/lib';\n\nconst nest = new Nest\u003cUnknownNest\u003e({\n  foo: { bar: 'zoo' }\n});\n\nregistry.set('foo', 'zoo', ['foo', 'bar', 'zoo'])\n\nnest.has('foo') //--\u003e true\nnest.has('foo', 'bar') //--\u003e true\nnest.has('bar', 'foo') //--\u003e false\nnest.get('foo', 'zoo') //--\u003e ['foo', 'bar', 'zoo']\nnest.get('foo', 'zoo', 1) //--\u003e 'bar'\nnest.get\u003cstring\u003e('foo', 'zoo', 1) // as string\n\nregistry.remove('foo', 'bar')\n\nnest.has('foo', 'bar') //--\u003e false\nnest.has('foo', 'zoo') //--\u003e true\n```\n\n\u003ca name=\"rmap\"\u003e\u003c/a\u003e\n\n### Readonly Map\n\nA type of `Map` that is readonly.\n\n```js\nimport { ReadonlyMap } from  '@stackpress/lib';\n\nconst map = new ReadonlyMap([['foo', 'bar'], ['bar', 'zoo']]);\n\nmap.get('foo') //--\u003e bar\nmap.has('bar') //--\u003e zoo\n\nmap.entries() //--\u003e [['foo', 'bar'], ['bar', 'zoo']]\n\nmap.forEach(console.log);\n```\n\n\u003ca name=\"rnest\"\u003e\u003c/a\u003e\n\n### Readonly Nest\n\nA type of `Nest` that is readonly.\n\n```js\nimport { ReadonlyNest, UnknownNest } from '@stackpress/lib';\n\nconst nest = new Nest\u003cUnknownNest\u003e({\n  foo: { bar: 'zoo' }\n});\n\nnest.has('foo') //--\u003e true\nnest.has('foo', 'bar') //--\u003e true\nnest.has('bar', 'foo') //--\u003e false\nnest.get('foo', 'zoo') //--\u003e ['foo', 'bar', 'zoo']\nnest.get('foo', 'zoo', 1) //--\u003e 'bar'\nnest.get\u003cstring\u003e('foo', 'zoo', 1) // as string\n```\n\n\u003ca name=\"rset\"\u003e\u003c/a\u003e\n\n### Readonly Set\n\nA type of `Set` that is readonly.\n\n```js\nimport { ReadonlySet } from  '@stackpress/lib';\n\nconst set = new ReadonlySet(['foo', 'bar', 'zoo']);\n\nset.size //--\u003e 3\nset.has('bar') //--\u003e true\nset.values() //--\u003e ['foo', 'bar', 'zoo']\n\nset.forEach(console.log);\n```\n\n\u003ca name=\"event\"\u003e\u003c/a\u003e\n\n## Event\n\nThe event library is a set of tools for event driven projects.\n\n  - [EventEmitter](#emitter)\n  - [EventRouter](#router)\n  - [EventTerminal](#terminal)\n\n\u003ca name=\"emitter\"\u003e\u003c/a\u003e\n\n### EventEmitter\n\nA class that implements the observer pattern for handling events. \nThe interface follows `node:events`, but you can set priority levels per \nevent action. EventEmitter works on server and browser.\n\n```js\nimport { EventEmitter } from '@stackpress/lib';\n\ntype EventMap = Record\u003cstring, [ number ]\u003e \u0026 {\n  'trigger something': [ number ]\n};\n\nconst emitter = new EventEmitter\u003cEventMap\u003e()\n\nemitter.on('trigger something', async x =\u003e {\n  console.log('something triggered', x + 1)\n})\n\nemitter.on(/trigger (something)/, async x =\u003e {\n  console.log('(something) triggered', x + 2)\n}, 2)\n\nawait emitter.trigger('trigger something', 1)\n```\n\n\u003ca name=\"router\"\u003e\u003c/a\u003e\n\n### EventRouter\n\nAn `expressjs` like router that uses `EventEmitter` in the back-end.\nLike `EventEmitter`, you can set priority levels per route and works \nalso in the browser.\n\n```js\nimport { EventRouter } from '@stackpress/lib';\n\ntype RouteMap = Record\u003cstring, [ Map, Map ]\u003e;\n\nconst router = new EventRouter\u003cRouteMap\u003e()\n\nrouter.get('/foo/bar', async (req, res) =\u003e {\n  res.set('foo', 'bar')\n})\n\nrouter.all('/foo/bar', async (req, res) =\u003e {\n  res.set('bar', req.get('bar'))\n}, 2)\n\n//router.connect('/foo/bar', async (req, res) =\u003e {})\n//router.delete('/foo/bar', async (req, res) =\u003e {})\n//router.head('/foo/bar', async (req, res) =\u003e {})\n//router.options('/foo/bar', async (req, res) =\u003e {})\n//router.patch('/foo/bar', async (req, res) =\u003e {})\n//router.post('/foo/bar', async (req, res) =\u003e {})\n//router.put('/foo/bar', async (req, res) =\u003e {})\n//router.trace('/foo/bar', async (req, res) =\u003e {})\n//router.route('METHOD', '/foo/bar', async (req, res) =\u003e {})\n\nawait router.emit('GET /foo/bar', new Map([['foo', 'zoo']]), new Map())\n```\n\n\u003ca name=\"terminal\"\u003e\u003c/a\u003e\n\n### EventTerminal\n\nA basic event driven cli toolset that uses events in the background. \nThis enables using events on the command line.\n\n```js\nimport { EventTerminal } from '@stackpress/lib';\n\nconst cli = new EventTerminal(process.argv)\n\ncli.on('foo', async params =\u003e {\n  const foo = cli.expect([ 'foo', 'f' ], 'bar')\n  EventTerminal.info(foo) //--\u003e bar\n  console.log(params) //--\u003e { foo: 'bar' }\n})\n\nawait cli.run()\n```\n\n\u003ca name=\"queue\"\u003e\u003c/a\u003e\n\n## Queue\n\nThe queue library is used to order items like callbacks and return \nthe correct sequence.\n\n  - [ItemQueue](#item)\n  - [TaskQueue](#task)\n\n\u003ca name=\"item\"\u003e\u003c/a\u003e\n\n### ItemQueue\n\nAn item queue orders and consumes items sequencially (FIFO by default).\n\n```js\nimport { ItemQueue } from '@stackpress/lib';\n\nconst queue = new ItemQueue\u003cstring\u003e()\n\nqueue.push('a')\n\nqueue.shift('b')\n\nqueue.add('c', 10)\n\nqueue.consume() //--\u003e c\nqueue.consume() //--\u003e b\nqueue.consume() //--\u003e a\n```\n\n\u003ca name=\"task\"\u003e\u003c/a\u003e\n\n### TaskQueue\n\nA task queue orders and runs callbacks sequencially.\n\n```js\nimport { TaskQueue } from '@stackpress/lib';\n\nconst queue = new TaskQueue()\n\nqueue.push(async x =\u003e {\n  console.log(x + 1)\n})\n\nqueue.shift(async x =\u003e {\n  await Helper.sleep(2000)\n  console.log(x + 2)\n})\n\nqueue.add(async x =\u003e {\n  console.log(x + 3)\n}, 10)\n\nawait queue.run(1)\n```\n\n\u003ca name=\"system\"\u003e\u003c/a\u003e\n\n## FileSystem\n\nThe file system library is an interface to interact with various file \nsystems *(ie. node:fs, virtual fs, browser fs, webpack fs, etc..)* .\nIt just requires the minimum functions compared to `node:fs`. \n\n```js\ninterface FileSystem {\n  existsSync(path: string): boolean;\n  readFileSync(path: string, encoding: BufferEncoding): string;\n  realpathSync(string: string): string;\n  lstatSync(path: string): FileStat;\n  writeFileSync(path: string, data: string): void;\n  mkdirSync(path: string, options?: FileRecursiveOption): void\n  createReadStream(path: string): FileStream;\n  unlinkSync(path: string): void;\n};\n```\n\nA file loader is a set of common tools for locating, loading, importing \nfiles through out your project and `node_modules`.\n\n```js\nimport { NodeFS, FileLoader } from '@stackpress/lib';\n\nconst loader = new FileLoader(new NodeFS());\n\nloader.modules() //--\u003e ./node_modules/\nloader.relative('/path/from/source.file', '/path/to/destination.file') //--\u003e '../destination'\nloader.resolve('@/project/index') //--\u003e [cwd]/project/index.js\nloader.absolute('../project/index') //--\u003e [cwd]/project/index.js\n```\n\n\u003ca name=\"exception\"\u003e\u003c/a\u003e\n\n## Exception\n\nExceptions are used to give more information of an error that has occured.\n\n```js\nimport { Exception } from '@stackpress/lib';\n\nconst exception = new Exception('Invalid Parameters: %s', 2)\n  .withErrors({\n    name: 'required',\n    pass: 'missing number'\n  })\n  .withCode(500)\n  .withPosition(100, 200)\n\nexception.toResponse() //--\u003e \n/*{\n  code: 500,\n  status: 'Server Error',\n  error: 'Invalid Parameters 2',\n  start: 100,\n  end: 200\n}*/\n\nexception.trace() //--\u003e [{ method, file, line, char}, ...]\n\nthrow Exception.for('Unknown Error')\n```\n\n\u003ca name=\"reflection\"\u003e\u003c/a\u003e\n\n## Reflection\n\nUses `CallSite` to produce proper stack tracing and information about \nfunctions being executed.\n\n```js\nimport { Reflection } from '@stackpress/lib';\n\nconst reflection = Reflection.stack(); //--\u003e Reflection\n\nreflection[0].column //--\u003e 3\nreflection[0].file //--\u003e /path/to/file\nreflection[0].func //--\u003e Function\nreflection[0].funcName //--\u003e 'main'\nreflection[0].line //--\u003e 3\nreflection[0].method //--\u003e \u003cnone\u003e\nreflection[0].self //--\u003e undefined\nreflection[0].toObject()\n```\n\n\u003ca name=\"status\"\u003e\u003c/a\u003e\n\n## Status Codes\n\nStatus codes inherit from http status codes and can be used to report \nstatuses after major actions within your app has been executed.\n\n```js\nimport { Status, getStatus } from '@stackpress/lib';\n\ngetStatus(200) //--\u003e { code: 200, status: 'OK' }\n\nStatus.CONTINUE //--\u003e { code: 100, status: 'Continue' }\nStatus.PROCESSING //--\u003e { code: 102, status: 'Processing' }\nStatus.OK //--\u003e { code: 200, status: 'OK' }\nStatus.CREATED //--\u003e { code: 201, status: 'Created' }\nStatus.ACCEPTED //--\u003e { code: 202, status: 'Accepted' }\nStatus.EMPTY //--\u003e { code: 204, status: 'No Content' }\nStatus.RESET //--\u003e { code: 205, status: 'Reset Content' }\nStatus.PARTIAL //--\u003e { code: 206, status: 'Partial Content' }\nStatus.MOVED //--\u003e { code: 301, status: 'Moved Permanently' }\nStatus.FOUND //--\u003e { code: 302, status: 'Found' }\nStatus.REDIRECT //--\u003e { code: 303, status: 'See Other' }\nStatus.CACHE //--\u003e { code: 304, status: 'Not Modified' }\nStatus.TEMPORARY //--\u003e { code: 307, status: 'Temporary Redirect' }\nStatus.PERMANENT //--\u003e { code: 308, status: 'Permanent Redirect' }\nStatus.ABORT //--\u003e { code: 309, status: 'Aborted' }\nStatus.BAD_REQUEST //--\u003e { code: 400, status: 'Bad Request' }\nStatus.UNAUTHORIZED //--\u003e { code: 401, status: 'Unauthorized' }\nStatus.FORBIDDEN //--\u003e { code: 403, status: 'Forbidden' }\nStatus.NOT_FOUND //--\u003e { code: 404, status: 'Not Found' }\nStatus.BAD_METHOD //--\u003e { code: 405, status: 'Method Not Allowed' }\nStatus.NOT_ACCEPTABLE //--\u003e { code: 406, status: 'Not Acceptable' }\nStatus.REQUEST_TIMEOUT //--\u003e { code: 408, status: 'Request Timeout' }\nStatus.CONFLICT //--\u003e { code: 409, status: 'Conflict' }\nStatus.GONE //--\u003e { code: 410, status: 'Gone' }\nStatus.LENGTH_REQUIRED //--\u003e { code: 411, status: 'Length Required' }\nStatus.TOO_LARGE //--\u003e { code: 413, status: 'Payload Too Large' }\nStatus.TOO_LONG //--\u003e { code: 414, status: 'URI Too Long' }\nStatus.UNSUPPORTED_TYPE //--\u003e { code: 415, status: 'Unsupported Media Type' }\nStatus.BAD_RANGE //--\u003e { code: 416, status: 'Range Not Satisfiable' }\nStatus.BAD_EXPECTATION //--\u003e { code: 417, status: 'Expectation Failed' }\nStatus.MISDIRECTED //--\u003e { code: 421, status: 'Misdirected Request' }\nStatus.UNPROCESSABLE //--\u003e { code: 422, status: 'Unprocessable Content' }\nStatus.LOCKED //--\u003e { code: 423, status: 'Locked' }\nStatus.BAD_DEPENDENCY //--\u003e { code: 424, status: 'Failed Dependency' }\nStatus.UPGRADE_REQUIRED //--\u003e { code: 426, status: 'Upgrade Required' }\nStatus.BAD_PRECONDITION //--\u003e { code: 428, status: 'Precondition Required' }\nStatus.TOO_MANY //--\u003e { code: 429, status: 'Too Many Requests' }\nStatus.HEADER_TOO_LARGE //--\u003e { code: 431, status: 'Request Header Fields Too Large' }\nStatus.LEGAL_REASONS //--\u003e { code: 451, status: 'Unavailable For Legal Reasons' }\nStatus.ERROR //--\u003e { code: 500, status: 'Internal Server Error' }\nStatus.NOT_IMPLEMENTED //--\u003e { code: 501, status: 'Not Implemented' }\nStatus.BAD_GATEWAY //--\u003e { code: 502, status: 'Bad Gateway' }\nStatus.UNAVAILABLE //--\u003e { code: 503, status: 'Service Unavailable' }\nStatus.RESPONSE_TIMEOUT //--\u003e { code: 504, status: 'Gateway Timeout' }\nStatus.BAD_VERSION //--\u003e { code: 505, status: 'HTTP Version Not Supported' }\nStatus.INSUFFICIENT_STORAGE //--\u003e { code: 507, status: 'Insufficient Storage' }\nStatus.INFINITE_LOOP //--\u003e { code: 508, status: 'Loop Detected' }\nStatus.NETWORK_AUTHENTICATION_REQUIRED //--\u003e { code: 511, status: 'Network Authentication Required' }\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackpress%2Flib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstackpress%2Flib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackpress%2Flib/lists"}