{"id":50474391,"url":"https://github.com/shnwazdeveloper/shnwazdev-package","last_synced_at":"2026-06-01T12:02:58.835Z","repository":{"id":355895492,"uuid":"1230098515","full_name":"shnwazdeveloper/shnwazdev-package","owner":"shnwazdeveloper","description":"Personal npm package for shnwazdev utilities","archived":false,"fork":false,"pushed_at":"2026-05-05T18:55:13.000Z","size":149,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-05T19:35:00.336Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://shnwazdeveloper.github.io/shnwazdev-package/","language":"JavaScript","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/shnwazdeveloper.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-05T17:15:37.000Z","updated_at":"2026-05-05T18:55:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/shnwazdeveloper/shnwazdev-package","commit_stats":null,"previous_names":["shnwazdeveloper/shnwazdev-package"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/shnwazdeveloper/shnwazdev-package","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shnwazdeveloper%2Fshnwazdev-package","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shnwazdeveloper%2Fshnwazdev-package/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shnwazdeveloper%2Fshnwazdev-package/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shnwazdeveloper%2Fshnwazdev-package/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shnwazdeveloper","download_url":"https://codeload.github.com/shnwazdeveloper/shnwazdev-package/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shnwazdeveloper%2Fshnwazdev-package/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33773782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2026-06-01T12:02:54.008Z","updated_at":"2026-06-01T12:02:58.823Z","avatar_url":"https://github.com/shnwazdeveloper.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @shnwazdeveloper/shnwazdev\n\nSafe real-time utility toolkit for `shnwazdev` projects, published with GitHub Packages.\n\nUse this package when you need small, dependency-free helpers for live app state, event messages, API polling, bot status checks, retries, timeouts, fast UI input control, and safe logging that avoids leaking tokens or private data.\n\n## Package Links\n\n- Package: https://github.com/shnwazdeveloper/shnwazdev-package/pkgs/npm/shnwazdev\n- Repository: https://github.com/shnwazdeveloper/shnwazdev-package\n- Owner: `shnwazdeveloper`\n- Package name: `@shnwazdeveloper/shnwazdev`\n- Registry: `https://npm.pkg.github.com`\n\n## Install From GitHub Packages\n\nGitHub Packages does not use the normal public npm registry for this scoped package. Add this line to your user or project `.npmrc`:\n\n```ini\n@shnwazdeveloper:registry=https://npm.pkg.github.com\n```\n\nIf the package is installed on your own machine, connect npm to your GitHub token:\n\n```powershell\ngh auth refresh -h github.com -s read:packages\n$token = gh auth token\nnpm config set \"//npm.pkg.github.com/:_authToken\" \"$token\" --location=user\n```\n\nThen install:\n\n```bash\nnpm install @shnwazdeveloper/shnwazdev@0.4.0\n```\n\n## What Is Inside\n\n- `createEventBus` for app events and message passing\n- `createRealtimeStore` for live state with subscriptions and selectors\n- `createPoller` for APIs, bots, dashboards, and workers\n- `createHeartbeat` for live status checks\n- `sleep` for async delays\n- `timeout` for stopping slow promises\n- `retry` for retrying unstable operations\n- `debounce` for search boxes, resize handlers, and input events\n- `throttle` for scroll, mousemove, and high-frequency events\n- `redactSensitiveData` for removing passwords, tokens, cookies, and keys\n- `detectSecrets` for finding sensitive values without printing raw secrets\n- `assertNoSecrets` for failing fast when a payload contains sensitive data\n- `safeJsonStringify` for circular-safe, redacted JSON output\n- `createSafeLogger` for console-style logging with automatic redaction\n- `maskSecret` for safe secret previews\n- `createSecureId` for crypto-safe request IDs and trace IDs\n- `constantTimeEqual` for safer token/signature comparisons\n- `sanitizeHeaders` for redacted header logs\n- `sanitizeUrl` for redacted URL logs\n- `createRateLimiter` for local abuse protection\n- `createCircuitBreaker` for failing safely when a dependency is unhealthy\n- `safeFetch` for timeout-aware, origin-guarded fetch calls with safe request logs\n\n## Quick Start\n\n```js\nimport {\n  createEventBus,\n  createPoller,\n  createRateLimiter,\n  createRealtimeStore,\n  createSafeLogger,\n  retry,\n  safeFetch,\n  timeout\n} from \"@shnwazdeveloper/shnwazdev\";\n\nconst store = createRealtimeStore({ online: false, users: 0 });\n\nstore.subscribe((state) =\u003e {\n  console.log(\"state changed\", state);\n});\n\nstore.setState({ online: true });\n\nconst bus = createEventBus();\nbus.on(\"message\", (message) =\u003e console.log(message.text));\nbus.emit(\"message\", { text: \"Hello from shnwazdev\" });\n\nconst poller = createPoller(\n  async () =\u003e {\n    const response = await fetch(\"https://api.github.com\");\n    return response.status;\n  },\n  { interval: 5000 }\n);\n\npoller.onData((status) =\u003e console.log(\"GitHub status\", status));\npoller.start();\n\nconst response = await retry(\n  () =\u003e timeout(fetch(\"https://api.github.com\"), 3000),\n  { retries: 2, delay: 500 }\n);\n\nconsole.log(response.status);\n\nconst logger = createSafeLogger(console);\nlogger.log(\"safe output\", {\n  username: \"shnwazdeveloper\",\n  token: \"example-token-that-will-be-redacted\"\n});\n\nconst limiter = createRateLimiter({ limit: 10, interval: 60000 });\nlimiter.assert(\"user:shnwazdeveloper\");\n\nconst { status, safeRequest } = await safeFetch(\"https://api.github.com\", {\n  allowedOrigins: [\"https://api.github.com\"],\n  timeout: 3000\n});\n\nlogger.info(\"request finished\", { status, safeRequest });\n```\n\n## Realtime Store\n\nUse `createRealtimeStore` when several parts of an app need to react to shared state.\n\n```js\nimport { createRealtimeStore } from \"@shnwazdeveloper/shnwazdev\";\n\nconst store = createRealtimeStore({ connected: false, count: 0 });\n\nconst unsubscribe = store.subscribe((nextState, previousState) =\u003e {\n  console.log({ nextState, previousState });\n});\n\nstore.select(\n  (state) =\u003e state.count,\n  (count) =\u003e console.log(\"count changed\", count)\n);\n\nstore.setState({ connected: true });\nstore.update((state) =\u003e ({ count: state.count + 1 }));\n\nawait store.waitFor((state) =\u003e state.count \u003e= 1, { timeout: 1000 });\n\nunsubscribe();\n```\n\n## Event Bus\n\nUse `createEventBus` for local publish/subscribe events.\n\n```js\nimport { createEventBus } from \"@shnwazdeveloper/shnwazdev\";\n\nconst bus = createEventBus();\n\nconst off = bus.on(\"user:joined\", (user) =\u003e {\n  console.log(`${user.name} joined`);\n});\n\nbus.once(\"ready\", () =\u003e {\n  console.log(\"ready only runs one time\");\n});\n\nbus.emit(\"user:joined\", { name: \"Shnwaz\" });\nbus.emit(\"ready\");\n\noff();\n```\n\n## Poller\n\nUse `createPoller` to repeatedly run async work.\n\n```js\nimport { createPoller } from \"@shnwazdeveloper/shnwazdev\";\n\nconst poller = createPoller(\n  async ({ runCount }) =\u003e {\n    const response = await fetch(\"https://api.github.com\");\n    return {\n      runCount,\n      ok: response.ok,\n      status: response.status\n    };\n  },\n  {\n    interval: 5000,\n    backoff: 2,\n    maxInterval: 30000\n  }\n);\n\npoller.onData((data) =\u003e console.log(\"data\", data));\npoller.onError((error) =\u003e console.error(\"poll failed\", error));\n\npoller.start();\n\nconst firstOk = await poller.until((data) =\u003e data.ok, { timeout: 20000 });\nconsole.log(firstOk);\n\npoller.stop();\n```\n\n## Heartbeat\n\nUse `createHeartbeat` when you want a small live signal for a bot, dashboard, worker, or connection monitor.\n\n```js\nimport { createHeartbeat } from \"@shnwazdeveloper/shnwazdev\";\n\nconst heartbeat = createHeartbeat({ interval: 1000 });\n\nheartbeat.onBeat((beat) =\u003e {\n  console.log(`beat ${beat.count}`, beat.lastBeatAt);\n});\n\nheartbeat.start();\n\nsetTimeout(() =\u003e {\n  heartbeat.stop();\n}, 5000);\n```\n\n## Timing Helpers\n\n```js\nimport {\n  debounce,\n  retry,\n  sleep,\n  throttle,\n  timeout\n} from \"@shnwazdeveloper/shnwazdev\";\n\nawait sleep(500);\n\nawait timeout(fetch(\"https://api.github.com\"), 3000);\n\nawait retry(\n  async () =\u003e {\n    const response = await fetch(\"https://api.github.com\");\n    if (!response.ok) {\n      throw new Error(\"GitHub request failed\");\n    }\n    return response;\n  },\n  { retries: 3, delay: 500, factor: 2 }\n);\n\nconst onSearch = debounce((query) =\u003e {\n  console.log(\"search\", query);\n}, 300);\n\nconst onScroll = throttle(() =\u003e {\n  console.log(\"scroll event\");\n}, 100);\n```\n\n## Safety And Data Protection\n\nUse these helpers before logging API responses, request headers, environment snapshots, bot session data, or errors. They are designed to keep useful structure while removing sensitive values.\n\n### Redact Sensitive Data\n\n```js\nimport { redactSensitiveData } from \"@shnwazdeveloper/shnwazdev\";\n\nconst safePayload = redactSensitiveData({\n  username: \"shnwazdeveloper\",\n  password: \"my-password\",\n  headers: {\n    authorization: \"Bearer real-token-value\"\n  }\n});\n\nconsole.log(safePayload);\n```\n\nOutput:\n\n```js\n{\n  username: \"shnwazdeveloper\",\n  password: \"[REDACTED]\",\n  headers: {\n    authorization: \"[REDACTED]\"\n  }\n}\n```\n\n### Detect Secrets Without Printing Them\n\n```js\nimport { detectSecrets } from \"@shnwazdeveloper/shnwazdev\";\n\nconst findings = detectSecrets({\n  apiKey: \"real-api-key-value\",\n  message: \"Bearer real-token-value\"\n});\n\nconsole.log(findings);\n```\n\nFindings include the path, type, and a masked preview. Raw secret values are not returned.\n\n### Fail Fast If Secrets Exist\n\n```js\nimport { assertNoSecrets } from \"@shnwazdeveloper/shnwazdev\";\n\nassertNoSecrets({\n  public: \"safe\",\n  token: \"private-token\"\n});\n```\n\nIf sensitive data is found, this throws a `SensitiveDataError`.\n\n### Safe JSON\n\n```js\nimport { safeJsonStringify } from \"@shnwazdeveloper/shnwazdev\";\n\nconst payload = { token: \"private-token\" };\npayload.self = payload;\n\nconsole.log(safeJsonStringify(payload));\n```\n\nThis handles circular objects and redacts sensitive values.\n\n### Safe Logger\n\n```js\nimport { createSafeLogger } from \"@shnwazdeveloper/shnwazdev\";\n\nconst logger = createSafeLogger(console);\n\nlogger.info(\"request\", {\n  user: \"shnwazdeveloper\",\n  cookie: \"private-cookie\",\n  token: \"private-token\"\n});\n```\n\nThe logger keeps normal fields and replaces sensitive fields with `[REDACTED]`.\n\n### Secure IDs And Safer Comparisons\n\n```js\nimport {\n  constantTimeEqual,\n  createSecureId\n} from \"@shnwazdeveloper/shnwazdev\";\n\nconst requestId = createSecureId({ prefix: \"req_\", size: 16 });\nconsole.log(requestId);\n\nif (constantTimeEqual(userInputToken, expectedToken)) {\n  console.log(\"token matched\");\n}\n```\n\n`createSecureId` uses crypto-safe random bytes. `constantTimeEqual` compares strings without returning early on the first different character.\n\n### Safe URL And Header Logging\n\n```js\nimport {\n  sanitizeHeaders,\n  sanitizeUrl\n} from \"@shnwazdeveloper/shnwazdev\";\n\nconsole.log(sanitizeUrl(\"https://example.com/search?q=node\u0026token=private\"));\n\nconsole.log(sanitizeHeaders({\n  authorization: \"Bearer private\",\n  accept: \"application/json\"\n}));\n```\n\nThis keeps useful debugging details while removing sensitive values.\n\n## Advanced Resilience Helpers\n\n### Rate Limiter\n\nUse `createRateLimiter` to protect local commands, bots, API handlers, and expensive tasks from repeated calls.\n\n```js\nimport { createRateLimiter } from \"@shnwazdeveloper/shnwazdev\";\n\nconst limiter = createRateLimiter({\n  limit: 5,\n  interval: 60000\n});\n\ntry {\n  limiter.assert(\"user:shnwazdeveloper\");\n  console.log(\"allowed\");\n} catch (error) {\n  console.log(error.name, error.retryAfter);\n}\n```\n\n### Circuit Breaker\n\nUse `createCircuitBreaker` around unstable downstream work. After too many failures, it opens and stops calling the failing task until the recovery time passes.\n\n```js\nimport { createCircuitBreaker } from \"@shnwazdeveloper/shnwazdev\";\n\nconst breaker = createCircuitBreaker(\n  async () =\u003e {\n    const response = await fetch(\"https://api.github.com\");\n    if (!response.ok) {\n      throw new Error(\"GitHub request failed\");\n    }\n    return response;\n  },\n  {\n    failureThreshold: 3,\n    recoveryTime: 30000\n  }\n);\n\nconst response = await breaker.execute();\nconsole.log(response.status);\n```\n\n### Safe Fetch\n\nUse `safeFetch` when you want origin checks, timeouts, and safe request metadata for logs.\n\n```js\nimport { safeFetch } from \"@shnwazdeveloper/shnwazdev\";\n\nconst result = await safeFetch(\"https://api.github.com\", {\n  allowedOrigins: [\"https://api.github.com\"],\n  timeout: 3000,\n  init: {\n    headers: {\n      authorization: \"Bearer private\",\n      accept: \"application/json\"\n    }\n  }\n});\n\nconsole.log(result.status);\nconsole.log(result.safeRequest);\n```\n\n`safeRequest` contains a sanitized URL and sanitized headers, so you can log it without exposing private data.\n\n## Development\n\nClone the repository:\n\n```bash\ngit clone https://github.com/shnwazdeveloper/shnwazdev-package.git\ncd shnwazdev-package\n```\n\nRun tests:\n\n```bash\nnpm test\n```\n\nCheck for accidental secrets:\n\n```bash\nnpm run secret:check\n```\n\nCheck what files will be published:\n\n```bash\nnpm run pack:check\n```\n\nRun every safety check before publishing:\n\n```bash\nnpm run safe:check\n```\n\n## Publish A New Version To Packages\n\nGitHub Actions publishes this package automatically when a version tag is pushed.\n\n1. Edit the code or README.\n2. Update `version` in `package.json`.\n3. Run checks:\n\n```bash\nnpm test\nnpm run secret:check\nnpm run pack:check\n```\n\n4. Commit and push:\n\n```bash\ngit add .\ngit commit -m \"Update package\"\ngit push origin main\n```\n\n5. Create and push a version tag:\n\n```bash\ngit tag v0.4.0\ngit push origin v0.4.0\n```\n\nAfter the tag is pushed, the `Publish Package` GitHub Actions workflow runs and publishes the new version to GitHub Packages.\n\n## How This Package Avoids Leaking Data\n\n- `.env` and `.env.*` are ignored by git.\n- `npm run secret:check` scans source/docs for common leaked token patterns.\n- `npm run safe:check` runs secret scanning, tests, and package dry-run together.\n- The CI workflow runs `safe:check` on pushes and pull requests.\n- The publish workflow runs secret scanning and tests before `npm publish`.\n- Runtime helpers redact sensitive keys like `password`, `token`, `secret`, `apiKey`, `authorization`, `cookie`, and `privateKey`.\n- Detection results only show masked previews, not raw secret values.\n- `safeFetch` can restrict calls to allowed origins and returns redacted request metadata for logs.\n- `createRateLimiter` and `createCircuitBreaker` help reduce repeated abuse and unsafe retry storms.\n\n## Troubleshooting\n\n### npm 404 from registry.npmjs.org\n\nThis means npm is looking in the wrong registry.\n\nFix:\n\n```bash\nnpm config set \"@shnwazdeveloper:registry\" \"https://npm.pkg.github.com\" --location=user\n```\n\n### npm 401 Unauthorized\n\nThis means npm is using GitHub Packages but does not have a token.\n\nFix:\n\n```powershell\ngh auth refresh -h github.com -s read:packages\n$token = gh auth token\nnpm config set \"//npm.pkg.github.com/:_authToken\" \"$token\" --location=user\n```\n\n### Package version already exists\n\nGitHub Packages does not let the same package version be published twice. Increase the `version` in `package.json`, then push a matching new tag.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshnwazdeveloper%2Fshnwazdev-package","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshnwazdeveloper%2Fshnwazdev-package","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshnwazdeveloper%2Fshnwazdev-package/lists"}