diff --git a/docs/nostr-patterns/replaceable-events.md b/docs/nostr-patterns/replaceable-events.md index f02158b..0cad379 100644 --- a/docs/nostr-patterns/replaceable-events.md +++ b/docs/nostr-patterns/replaceable-events.md @@ -7,19 +7,15 @@ in this file follows from that single fact. ## Strictly-monotonic `created_at` per coord -**Canonical helper:** `src/lib/nostr/timestamp.ts` — -`monotonicCreatedAt(lastCreatedAt, now?)` returns `max(now, last + 1)`. -Use it for **every** replaceable-event publish; track the last -`created_at` per coord (a `Map` when one composable -publishes many coords like `useRSVP.ts`, or a single field when there's -one coord per user like `useBookmarks.ts`' kind-10003 list). +**Canonical:** `src/modules/events/composables/useRSVP.ts` — +`lastPublishAt` map + the `Math.max(now, previous + 1)` line. ```ts -import { monotonicCreatedAt } from '@/lib/nostr/timestamp' - const lastPublishAt = new Map() -const createdAt = monotonicCreatedAt(lastPublishAt.get(coord)) +const now = Math.floor(Date.now() / 1000) +const previous = lastPublishAt.get(coord) ?? 0 +const createdAt = Math.max(now, previous + 1) … lastPublishAt.set(coord, signedEvent.created_at) // only after publish success ``` diff --git a/package.json b/package.json index d40f262..439cb84 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,6 @@ "build": "vue-tsc -b && vite build", "preview": "vite preview --host", "analyze": "vite build --mode analyze", - "test": "vitest run", - "test:watch": "vitest", "dev:events": "vite --host --config vite.events.config.ts", "build:events": "vue-tsc -b && vite build --config vite.events.config.ts", "preview:events": "vite preview --host --config vite.events.config.ts", @@ -109,7 +107,6 @@ "vite-plugin-image-optimizer": "^1.1.7", "vite-plugin-inspect": "^0.8.3", "vite-plugin-pwa": "^0.21.1", - "vitest": "^4.1.9", "vue-tsc": "^2.2.0", "web-push": "^3.6.7", "workbox-window": "^7.3.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f531eb5..c242e32 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -192,9 +192,6 @@ importers: vite-plugin-pwa: specifier: ^0.21.1 version: 0.21.2(@vite-pwa/assets-generator@1.0.2)(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))(workbox-build@7.4.1)(workbox-window@7.4.1) - vitest: - specifier: ^4.1.9 - version: 4.1.9(@types/node@22.19.19)(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)) vue-tsc: specifier: ^2.2.0 version: 2.2.12(typescript@5.6.3) @@ -1498,9 +1495,6 @@ packages: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@swc/helpers@0.5.21': resolution: {integrity: sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==} @@ -1641,12 +1635,6 @@ packages: '@types/cacheable-request@6.0.3': resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} - '@types/chai@5.2.3': - resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - - '@types/deep-eql@4.0.2': - resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -1730,35 +1718,6 @@ packages: vite: ^5.0.0 || ^6.0.0 vue: ^3.2.25 - '@vitest/expect@4.1.9': - resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} - - '@vitest/mocker@4.1.9': - resolution: {integrity: sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==} - peerDependencies: - msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - '@vitest/pretty-format@4.1.9': - resolution: {integrity: sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==} - - '@vitest/runner@4.1.9': - resolution: {integrity: sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==} - - '@vitest/snapshot@4.1.9': - resolution: {integrity: sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==} - - '@vitest/spy@4.1.9': - resolution: {integrity: sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==} - - '@vitest/utils@4.1.9': - resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} - '@volar/language-core@2.4.15': resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==} @@ -2070,10 +2029,6 @@ packages: asn1.js@5.4.1: resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -2215,10 +2170,6 @@ packages: caniuse-lite@1.0.30001793: resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==} - chai@6.2.2: - resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} - engines: {node: '>=18'} - chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -2662,9 +2613,6 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -2688,10 +2636,6 @@ packages: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} - expect-type@1.3.0: - resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} - engines: {node: '>=12.0.0'} - exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} @@ -3652,10 +3596,6 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - obug@2.1.3: - resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} - engines: {node: '>=12.20.0'} - ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} @@ -3786,9 +3726,6 @@ packages: pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pe-library@1.0.1: resolution: {integrity: sha512-nh39Mo1eGWmZS7y+mK/dQIqg7S1lp38DpRxkyoHf0ZcUs/HDc+yyTjuOtTvSMZHmfSLuSQaX945u05Y2Q6UWZg==} engines: {node: '>=14', npm: '>=7'} @@ -4162,9 +4099,6 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -4245,12 +4179,6 @@ packages: resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@4.1.0: - resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} - stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -4418,21 +4346,10 @@ packages: tiny-each-async@2.0.3: resolution: {integrity: sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA==} - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinyexec@1.2.4: - resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} - engines: {node: '>=18'} - tinyglobby@0.2.16: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} - tinyrainbow@3.1.0: - resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} - engines: {node: '>=14.0.0'} - tmp-promise@3.0.3: resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} @@ -4667,47 +4584,6 @@ packages: yaml: optional: true - vitest@4.1.9: - resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.9 - '@vitest/browser-preview': 4.1.9 - '@vitest/browser-webdriverio': 4.1.9 - '@vitest/coverage-istanbul': 4.1.9 - '@vitest/coverage-v8': 4.1.9 - '@vitest/ui': 4.1.9 - happy-dom: '*' - jsdom: '*' - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@opentelemetry/api': - optional: true - '@types/node': - optional: true - '@vitest/browser-playwright': - optional: true - '@vitest/browser-preview': - optional: true - '@vitest/browser-webdriverio': - optional: true - '@vitest/coverage-istanbul': - optional: true - '@vitest/coverage-v8': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} @@ -4828,11 +4704,6 @@ packages: engines: {node: '>= 8'} hasBin: true - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -6552,8 +6423,6 @@ snapshots: '@sindresorhus/is@4.6.0': {} - '@standard-schema/spec@1.1.0': {} - '@swc/helpers@0.5.21': dependencies: tslib: 2.8.1 @@ -6670,13 +6539,6 @@ snapshots: '@types/node': 22.19.19 '@types/responselike': 1.0.3 - '@types/chai@5.2.3': - dependencies: - '@types/deep-eql': 4.0.2 - assertion-error: 2.0.1 - - '@types/deep-eql@4.0.2': {} - '@types/estree@1.0.8': {} '@types/estree@1.0.9': {} @@ -6765,47 +6627,6 @@ snapshots: vite: 6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0) vue: 3.5.34(typescript@5.6.3) - '@vitest/expect@4.1.9': - dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.1.9 - '@vitest/utils': 4.1.9 - chai: 6.2.2 - tinyrainbow: 3.1.0 - - '@vitest/mocker@4.1.9(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))': - dependencies: - '@vitest/spy': 4.1.9 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0) - - '@vitest/pretty-format@4.1.9': - dependencies: - tinyrainbow: 3.1.0 - - '@vitest/runner@4.1.9': - dependencies: - '@vitest/utils': 4.1.9 - pathe: 2.0.3 - - '@vitest/snapshot@4.1.9': - dependencies: - '@vitest/pretty-format': 4.1.9 - '@vitest/utils': 4.1.9 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@4.1.9': {} - - '@vitest/utils@4.1.9': - dependencies: - '@vitest/pretty-format': 4.1.9 - convert-source-map: 2.0.0 - tinyrainbow: 3.1.0 - '@volar/language-core@2.4.15': dependencies: '@volar/source-map': 2.4.15 @@ -7167,8 +6988,6 @@ snapshots: minimalistic-assert: 1.0.1 safer-buffer: 2.1.2 - assertion-error@2.0.1: {} - async-function@1.0.0: {} async@3.2.6: {} @@ -7332,8 +7151,6 @@ snapshots: caniuse-lite@1.0.30001793: {} - chai@6.2.2: {} - chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -7870,10 +7687,6 @@ snapshots: estree-walker@2.0.2: {} - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.9 - esutils@2.0.3: {} eta@3.5.0: {} @@ -7894,8 +7707,6 @@ snapshots: signal-exit: 3.0.7 strip-eof: 1.0.0 - expect-type@1.3.0: {} - exponential-backoff@3.1.3: {} external-editor@3.1.0: @@ -8837,8 +8648,6 @@ snapshots: has-symbols: 1.1.0 object-keys: 1.1.1 - obug@2.1.3: {} - ohash@2.0.11: {} once@1.4.0: @@ -8957,8 +8766,6 @@ snapshots: pathe@1.1.2: {} - pathe@2.0.3: {} - pe-library@1.0.1: {} pend@1.2.0: {} @@ -9407,8 +9214,6 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - siginfo@2.0.0: {} - signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -9485,10 +9290,6 @@ snapshots: dependencies: minipass: 3.3.6 - stackback@0.0.2: {} - - std-env@4.1.0: {} - stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -9657,17 +9458,11 @@ snapshots: tiny-each-async@2.0.3: optional: true - tinybench@2.9.0: {} - - tinyexec@1.2.4: {} - tinyglobby@0.2.16: dependencies: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - tinyrainbow@3.1.0: {} - tmp-promise@3.0.3: dependencies: tmp: 0.2.5 @@ -9879,33 +9674,6 @@ snapshots: lightningcss: 1.32.0 terser: 5.48.0 - vitest@4.1.9(@types/node@22.19.19)(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)): - dependencies: - '@vitest/expect': 4.1.9 - '@vitest/mocker': 4.1.9(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)) - '@vitest/pretty-format': 4.1.9 - '@vitest/runner': 4.1.9 - '@vitest/snapshot': 4.1.9 - '@vitest/spy': 4.1.9 - '@vitest/utils': 4.1.9 - es-module-lexer: 2.1.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.3 - pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.1.0 - tinybench: 2.9.0 - tinyexec: 1.2.4 - tinyglobby: 0.2.16 - tinyrainbow: 3.1.0 - vite: 6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 22.19.19 - transitivePeerDependencies: - - msw - vscode-uri@3.1.0: {} vue-demi@0.14.10(vue@3.5.34(typescript@5.6.3)): @@ -10068,11 +9836,6 @@ snapshots: dependencies: isexe: 2.0.0 - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - word-wrap@1.2.5: optional: true diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index cacfb8c..34f4bc6 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -71,8 +71,6 @@ const messages: LocaleMessages = { past: 'Past', filters: 'Filters', clearAll: 'Clear all', - filteringBy: 'Filtering by:', - removeCategory: 'Remove {category} filter', }, categories: { concert: 'Concert', diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index 898352b..048c71a 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -71,8 +71,6 @@ const messages: LocaleMessages = { past: 'Pasado', filters: 'Filtros', clearAll: 'Limpiar todo', - filteringBy: 'Filtrando por:', - removeCategory: 'Quitar el filtro {category}', }, categories: { concert: 'Concierto', diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index 9638e69..57b3797 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -71,8 +71,6 @@ const messages: LocaleMessages = { past: 'Passé', filters: 'Filtres', clearAll: 'Tout effacer', - filteringBy: 'Filtré par :', - removeCategory: 'Retirer le filtre {category}', }, categories: { concert: 'Concert', diff --git a/src/i18n/types.ts b/src/i18n/types.ts index ecdf42f..f4177ba 100644 --- a/src/i18n/types.ts +++ b/src/i18n/types.ts @@ -72,8 +72,6 @@ export interface LocaleMessages { past: string filters: string clearAll: string - filteringBy: string - removeCategory: string } categories: Record detail: { diff --git a/src/lib/nostr/timestamp.spec.ts b/src/lib/nostr/timestamp.spec.ts deleted file mode 100644 index 3e5c099..0000000 --- a/src/lib/nostr/timestamp.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { describe, it, expect } from 'vitest' -import { monotonicCreatedAt } from './timestamp' - -describe('monotonicCreatedAt', () => { - it('uses now when there is no prior version', () => { - expect(monotonicCreatedAt(null, 1000)).toBe(1000) - expect(monotonicCreatedAt(undefined, 1000)).toBe(1000) - }) - - it('bumps to prior+1 when republished in the same second', () => { - // now == last: a naive floor(Date.now()/1000) would tie and the relay - // would drop the update; we must produce a strictly newer stamp. - expect(monotonicCreatedAt(1000, 1000)).toBe(1001) - }) - - it('tracks wall-clock once enough real seconds have elapsed', () => { - expect(monotonicCreatedAt(1000, 1005)).toBe(1005) - }) - - it('steps past a future-dated prior (clock skew / rapid bursts)', () => { - expect(monotonicCreatedAt(2000, 1000)).toBe(2001) - }) - - it('is strictly increasing across a same-second burst', () => { - let last: number | null = null - const stamps: number[] = [] - for (let i = 0; i < 5; i++) { - last = monotonicCreatedAt(last, 1000) // clock frozen at 1000 - stamps.push(last) - } - expect(stamps).toEqual([1000, 1001, 1002, 1003, 1004]) - for (let i = 1; i < stamps.length; i++) { - expect(stamps[i]).toBeGreaterThan(stamps[i - 1]) - } - }) -}) diff --git a/src/lib/nostr/timestamp.ts b/src/lib/nostr/timestamp.ts deleted file mode 100644 index 62bc899..0000000 --- a/src/lib/nostr/timestamp.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Monotonic `created_at` for replaceable / addressable Nostr events. - * - * Relays only push a replaceable update to OPEN subscriptions when its - * `created_at` is **strictly newer** than the version they already hold - * (verified against our relay). `created_at` is second-resolution, so a - * publisher that stamps `Math.floor(Date.now() / 1000)` can emit two - * versions within the same wall-clock second — the relay treats the - * second as not-newer and never propagates it to live subscribers (it - * only surfaces on a reload / fresh REQ). This is exactly the failure - * seen with rapid bookmark toggles. - * - * Returning `max(now, lastCreatedAt + 1)` guarantees a strictly - * increasing timestamp across successive publishes of the same - * replaceable event, so each version reaches open subscriptions. When - * enough real seconds have elapsed it tracks wall-clock; only same-second - * (or clock-skewed) republishes get nudged forward. - * - * @param lastCreatedAt `created_at` of the previously published version - * (seconds), or null/undefined if none has been published yet. - * @param now Current time in **seconds** — injectable for tests; defaults - * to `Math.floor(Date.now() / 1000)`. - */ -export function monotonicCreatedAt( - lastCreatedAt?: number | null, - now: number = Math.floor(Date.now() / 1000), -): number { - if (lastCreatedAt == null) return now - return Math.max(now, lastCreatedAt + 1) -} diff --git a/src/modules/events/components/EventCalendarPopup.vue b/src/modules/events/components/EventCalendarPopup.vue index 546c16f..955d805 100644 --- a/src/modules/events/components/EventCalendarPopup.vue +++ b/src/modules/events/components/EventCalendarPopup.vue @@ -1,6 +1,5 @@