{"id":22010474,"url":"https://github.com/virtualstate/internal","last_synced_at":"2026-05-07T04:31:44.656Z","repository":{"id":207682856,"uuid":"719845399","full_name":"virtualstate/internal","owner":"virtualstate","description":null,"archived":false,"fork":false,"pushed_at":"2024-02-14T09:03:43.000Z","size":3069,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-03-15T11:23:01.553Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/virtualstate.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE-OF-CONDUCT.md","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":"2023-11-17T02:41:43.000Z","updated_at":"2023-11-17T02:47:22.000Z","dependencies_parsed_at":"2024-11-30T02:13:15.250Z","dependency_job_id":"20861b26-0da6-400a-80e6-ddcb17b226e9","html_url":"https://github.com/virtualstate/internal","commit_stats":null,"previous_names":["virtualstate/internal"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtualstate%2Finternal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtualstate%2Finternal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtualstate%2Finternal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/virtualstate%2Finternal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/virtualstate","download_url":"https://codeload.github.com/virtualstate/internal/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245072249,"owners_count":20556353,"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":"2024-11-30T02:13:11.935Z","updated_at":"2025-10-25T11:39:54.224Z","avatar_url":"https://github.com/virtualstate.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @virtualstate/internal \n\n[//]: # (badges)\n\n### Support\n\n ![Node.js supported](https://img.shields.io/badge/node-%3E%3D18.7.0-blue) ![Bun supported](https://img.shields.io/badge/bun-%3E%3D1.0.2-blue) \n\n### Test Coverage\n\n\n\n[//]: # (badges)\n\n# Usage\n\n## [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)\n\n[`worker.js`](src/tests/readme/worker/worker.js)\n```javascript\nself.addEventListener(\"fetch\", event =\u003e {\n    console.log(event.request.method, event.request.url);\n    event.respondWith(new Response(\"Hello\"))\n});\n```\n\n[`main.js`](src/tests/readme/worker/main.js)\n```javascript\nimport { serviceWorker, createServiceWorkerFetch } from \"@virtualstate/internal\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\n\nconst pathname = fileURLToPath(import.meta.url);\nconst worker = join(dirname(pathname), \"./worker.js\");\n\nconst registration = await serviceWorker.register(worker);\n\nconst fetch = createServiceWorkerFetch(registration);\n\nconst response = await fetch(\"/\");\nconst text = await response.text();\n\nconsole.log(response.status, text); // 200 \"Hello\";\n```\n\n```bash\nREDIS_MEMORY=1 node main.js\n```\n\n## [CacheStorage](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage)\n\n[cache.js](./src/tests/readme/cache/cache.js)\n```javascript\nimport { caches } from \"@virtualstate/internal\";\n\nconst cache = await caches.open(\"cache\");\n\nconst url = \"https://example.com\";\n\nawait cache.add(url);\n\nconst response = await cache.match(url);\nconst text = await response.text();\n\nconsole.log(response.status, text.substring(0, 15), text.length); // 200 \"\u003c!doctype html\u003e\" 1256;\n```\n\n## [ContentIndex](https://developer.mozilla.org/en-US/docs/Web/API/ContentIndex)\n\n[index.js]()\n```javascript\nimport { index, caches } from \"@virtualstate/internal\";\n\nconst entry = {\n    id: \"post-1\",\n    url: \"/posts/amet.html\",\n    title: \"Amet consectetur adipisicing\",\n    description:\n        \"Repellat et quia iste possimus ducimus aliquid a aut eaque nostrum.\",\n    icons: [\n        {\n            src: \"https://javascript.org.nz/logo.png\",\n            sizes: \"200x200\",\n            type: \"image/png\",\n        },\n    ],\n    category: \"article\",\n};\nawait index.add(entry);\n\nconsole.log(await index.getAll()) // [{ id: \"post-1\" }]\n\nconst cache = await caches.open(\"contentIndex\");\n\nfor (const { src } of entry.icons) {\n    const response = await cache.match(src);\n    const { byteLength } = await response.arrayBuffer();\n    console.log(src, response.status, byteLength) // ... 200 5348\n}\n```\n\n## [Background Sync API](https://developer.mozilla.org/en-US/docs/Web/API/Background_Synchronization_API)\n\n[sync.js](src/tests/readme/sync/sync.js)\n```javascript\nimport { addEventListener, sync, caches, index, dispatchEvent } from \"@virtualstate/internal\";\n\naddEventListener(\"sync\", ({ tag, waitUntil }) =\u003e {\n    if (tag === \"images\") {\n        waitUntil(onSyncImages());\n    }\n\n    async function onSyncImages() {\n        const cache = await caches.open(\"contentIndex\");\n        for (const { id, icons } of await index.getAll()) {\n            for (const { src } of icons) {\n                console.log(`Updating icon \"${src}\" for ${id}`);\n                await cache.put(\n                    src,\n                    await fetch(src)\n                );\n            }\n        }\n    }\n});\n\nawait sync.register(\"images\");\n\n// Ran elsewhere by scheduler\n// Is usually managed by generateVirtualSyncEvents \nawait dispatchEvent({\n    type: \"sync\",\n    tag: \"images\",\n    schedule: {\n        immediate: true\n    }\n});\n```\n\n## [Periodic Sync API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Periodic_Background_Synchronization_API)\n\n[`periodic-sync.js`](src/tests/readme/periodic-sync/periodic-sync.js)\n```javascript\nimport { addEventListener, periodicSync, caches, index, dispatchEvent } from \"@virtualstate/internal\";\n\naddEventListener(\"periodicsync\", ({ tag, waitUntil }) =\u003e {\n    if (tag === \"images\") {\n        waitUntil(onSyncImages());\n    }\n\n    async function onSyncImages() {\n        const cache = await caches.open(\"contentIndex\");\n        for (const { id, icons } of await index.getAll()) {\n            for (const { src } of icons) {\n                console.log(`Updating icon \"${src}\" for ${id}`);\n                await cache.put(\n                    src,\n                    await fetch(src)\n                );\n            }\n        }\n    }\n});\n\nawait periodicSync.register(\"images\", {\n    minInterval: 5 * 60 * 1000 // Refresh every 5 minutes\n});\n\n// Ran elsewhere by scheduler\n// Is usually managed by generatePeriodicSyncVirtualEvents\nawait dispatchEvent({\n    type: \"periodicsync\",\n    tag: \"images\",\n    schedule: {\n        immediate: true\n        // can give delay here or cron\n        // minInterval doesn't always mean a fixed rate\n        //\n        // delay: 5 * 60 * 1000,\n        // repeat: true\n    }\n});\n```\n\n## Events\n\n```javascript\nimport { addEventListener, dispatchEvent } from \"@virtualstate/internal\";\n\naddEventListener(\"bingpop\", () =\u003e {\n    console.log(\"Received bingpop event\");\n});\n\ndispatchEvent({\n    type: \"bingpop\"\n});\n```\n\n### Schedules\n\n#### `schedule.immediate`\n\nUse this to have the event be dispatched immediately\n\n```javascript\ndispatchEvent({\n    type: \"bingpop\",\n    schedule: {\n        immediate: true\n    }\n});\n```\n\n#### `schedule.delay`\n\nUse this to have the event be dispatched after a period of time\n\n```javascript\ndispatchEvent({\n    type: \"bingpop\",\n    schedule: {\n        delay: 1000\n    }\n});\n```\n\n```javascript\ndispatchEvent({\n    type: \"bingpop\",\n    schedule: {\n        delay: \"1h\"\n    }\n});\n```\n\n#### `schedule.cron`\n\nUse this to have the event be dispatched according to a [cron schedule](https://crontab.guru/)\n\n```javascript\ndispatchEvent({\n    type: \"bingpop\",\n    schedule: {\n        // Triggers at 5am each day\n        cron: \"0 5 * * *\"\n    }\n});\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvirtualstate%2Finternal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvirtualstate%2Finternal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvirtualstate%2Finternal/lists"}