zooid 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +8 -1
  2. package/dist/bin.js +923 -184
  3. package/dist/bin.js.map +1 -1
  4. package/dist/{chunk-3Q4BPAZD.js → chunk-R5S26T7B.js} +20576 -514
  5. package/dist/chunk-R5S26T7B.js.map +1 -0
  6. package/dist/index.d.ts +3 -3
  7. package/dist/index.js +1 -1
  8. package/package.json +13 -9
  9. package/src/bin.test.ts +63 -0
  10. package/src/bin.ts +52 -3
  11. package/src/bootstrap/configs.test.ts +7 -0
  12. package/src/bootstrap/configs.ts +14 -0
  13. package/src/build-registry.context.test.ts +3 -3
  14. package/src/build-registry.ts +67 -24
  15. package/src/commands/dev.ts +37 -7
  16. package/src/commands/status.test.ts +15 -0
  17. package/src/commands/status.ts +27 -2
  18. package/src/daemon/delivery-cache.test.ts +34 -0
  19. package/src/daemon/delivery-cache.ts +36 -0
  20. package/src/daemon/load-custom-verifiers.ts +43 -0
  21. package/src/daemon/start-daemon.ts +177 -39
  22. package/src/daemon/task-journal.test.ts +19 -0
  23. package/src/daemon/task-journal.ts +32 -0
  24. package/src/daemon/trigger-rooms.test.ts +60 -0
  25. package/src/daemon/trigger-rooms.ts +0 -0
  26. package/src/daemon/trigger-runner.test.ts +71 -0
  27. package/src/daemon/trigger-runner.ts +41 -0
  28. package/src/daemon/trigger-scheduler.ts +55 -0
  29. package/src/daemon/webhook-routes.test.ts +74 -0
  30. package/src/daemon/webhook-routes.ts +202 -0
  31. package/src/daemon/webhook-verify.test.ts +155 -0
  32. package/src/daemon/webhook-verify.ts +155 -0
  33. package/src/pi-extension-install.test.ts +65 -0
  34. package/src/pi-extension-install.ts +56 -0
  35. package/src/push-gateway/gateway.test.ts +150 -0
  36. package/src/push-gateway/gateway.ts +78 -0
  37. package/src/push-gateway/index.ts +17 -0
  38. package/src/push-gateway/payload.test.ts +88 -0
  39. package/src/push-gateway/payload.ts +39 -0
  40. package/src/push-gateway/types.ts +37 -0
  41. package/src/push-gateway/vapid.test.ts +45 -0
  42. package/src/push-gateway/vapid.ts +34 -0
  43. package/src/services/tuwunel.ts +21 -2
  44. package/src/version.test.ts +67 -0
  45. package/src/version.ts +30 -0
  46. package/src/web/static.test.ts +22 -0
  47. package/src/web/static.ts +9 -1
  48. package/dist/chunk-3Q4BPAZD.js.map +0 -1
@@ -0,0 +1,67 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
3
+ import { tmpdir } from 'node:os'
4
+ import { join } from 'node:path'
5
+ import { pathToFileURL } from 'node:url'
6
+ import { readFileSync } from 'node:fs'
7
+ import { CLI_VERSION, readCliVersion } from './version.js'
8
+
9
+ const manifestVersion = (
10
+ JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as {
11
+ version: string
12
+ }
13
+ ).version
14
+
15
+ describe('readCliVersion', () => {
16
+ it('reports the version from the package manifest', () => {
17
+ expect(readCliVersion()).toBe(manifestVersion)
18
+ })
19
+
20
+ // The regression this exists for: `cli.version()` was a hardcoded '0.0.1'
21
+ // from the first release through 0.12.0, so every published build claimed
22
+ // to be a version that was never released.
23
+ it('is not a hardcoded placeholder', () => {
24
+ expect(CLI_VERSION).toBe(manifestVersion)
25
+ expect(CLI_VERSION).not.toBe('0.0.1')
26
+ expect(CLI_VERSION).toMatch(/^\d+\.\d+\.\d+/)
27
+ })
28
+
29
+ // dist/bin.js and src/bin.ts are the same depth from package.json, so the
30
+ // single '../package.json' has to work from either. Simulate the built
31
+ // bundle's location rather than trusting that they stay in step.
32
+ it('resolves from a sibling directory the way dist/ does', () => {
33
+ const root = mkdtempSync(join(tmpdir(), 'zooid-version-'))
34
+ try {
35
+ writeFileSync(join(root, 'package.json'), JSON.stringify({ version: '9.9.9' }))
36
+ const fromDist = pathToFileURL(join(root, 'dist', 'bin.js')).href
37
+ expect(readCliVersion(fromDist)).toBe('9.9.9')
38
+ const fromSrc = pathToFileURL(join(root, 'src', 'bin.ts')).href
39
+ expect(readCliVersion(fromSrc)).toBe('9.9.9')
40
+ } finally {
41
+ rmSync(root, { recursive: true, force: true })
42
+ }
43
+ })
44
+
45
+ it('falls back to "unknown" rather than throwing when the manifest is missing', () => {
46
+ const root = mkdtempSync(join(tmpdir(), 'zooid-version-'))
47
+ try {
48
+ const url = pathToFileURL(join(root, 'dist', 'bin.js')).href
49
+ expect(readCliVersion(url)).toBe('unknown')
50
+ } finally {
51
+ rmSync(root, { recursive: true, force: true })
52
+ }
53
+ })
54
+
55
+ it('falls back to "unknown" on a manifest with no usable version', () => {
56
+ const root = mkdtempSync(join(tmpdir(), 'zooid-version-'))
57
+ try {
58
+ writeFileSync(join(root, 'package.json'), JSON.stringify({ name: 'zooid' }))
59
+ const url = pathToFileURL(join(root, 'dist', 'bin.js')).href
60
+ expect(readCliVersion(url)).toBe('unknown')
61
+ writeFileSync(join(root, 'package.json'), '{not json')
62
+ expect(readCliVersion(url)).toBe('unknown')
63
+ } finally {
64
+ rmSync(root, { recursive: true, force: true })
65
+ }
66
+ })
67
+ })
package/src/version.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { readFileSync } from 'node:fs'
2
+
3
+ /**
4
+ * The CLI's own version, read from the package manifest at startup.
5
+ *
6
+ * Never hardcode this. A literal goes stale on the very next release, and
7
+ * `zooid --version` then lies about which build is installed — which is
8
+ * exactly what it did from the first release through 0.12.0, where it
9
+ * reported `0.0.1` forever.
10
+ *
11
+ * `dist/bin.js` (the published bundle) and `src/bin.ts` (a source run under
12
+ * tsx) sit at the same depth relative to package.json, so a single
13
+ * `../package.json` works for both without a build-time define.
14
+ *
15
+ * `url` is overridable for tests.
16
+ */
17
+ export function readCliVersion(url: string = import.meta.url): string {
18
+ try {
19
+ const manifest = new URL('../package.json', url)
20
+ const raw = JSON.parse(readFileSync(manifest, 'utf8')) as { version?: unknown }
21
+ if (typeof raw.version === 'string' && raw.version) return raw.version
22
+ return 'unknown'
23
+ } catch {
24
+ // A missing or malformed manifest must never stop the CLI from running —
25
+ // `--version` is the least important thing it does.
26
+ return 'unknown'
27
+ }
28
+ }
29
+
30
+ export const CLI_VERSION = readCliVersion()
@@ -48,4 +48,26 @@ describe('webStatic', () => {
48
48
  const r = await app.request('/assets/nope.js')
49
49
  expect(r.status).toBe(404)
50
50
  })
51
+
52
+ it('serves push_gateway_url and vapid_public_key when configured', async () => {
53
+ const app = webStatic({
54
+ webRoot: dir,
55
+ homeserverUrl: 'http://localhost:8448',
56
+ pushGatewayUrl: 'http://host.docker.internal:9000/_matrix/push/v1/notify',
57
+ vapidPublicKey: 'BPk',
58
+ })
59
+ const res = await app.request('/config.json')
60
+ expect(await res.json()).toEqual({
61
+ homeserver_url: 'http://localhost:8448',
62
+ push_gateway_url: 'http://host.docker.internal:9000/_matrix/push/v1/notify',
63
+ vapid_public_key: 'BPk',
64
+ })
65
+ })
66
+
67
+ it('omits both when unconfigured, so the client falls back instead of half-subscribing', async () => {
68
+ const app = webStatic({ webRoot: dir, homeserverUrl: 'http://localhost:8448' })
69
+ expect(await (await app.request('/config.json')).json()).toEqual({
70
+ homeserver_url: 'http://localhost:8448',
71
+ })
72
+ })
51
73
  })
package/src/web/static.ts CHANGED
@@ -5,6 +5,8 @@ import { Hono } from 'hono'
5
5
  export interface WebStaticOpts {
6
6
  webRoot: string
7
7
  homeserverUrl: string
8
+ pushGatewayUrl?: string
9
+ vapidPublicKey?: string
8
10
  }
9
11
 
10
12
  const MIME: Record<string, string> = {
@@ -28,7 +30,13 @@ function isAssetPath(p: string): boolean {
28
30
  export function webStatic(opts: WebStaticOpts): Hono {
29
31
  const app = new Hono()
30
32
 
31
- app.get('/config.json', (c) => c.json({ homeserver_url: opts.homeserverUrl }))
33
+ app.get('/config.json', (c) =>
34
+ c.json({
35
+ homeserver_url: opts.homeserverUrl,
36
+ ...(opts.pushGatewayUrl ? { push_gateway_url: opts.pushGatewayUrl } : {}),
37
+ ...(opts.vapidPublicKey ? { vapid_public_key: opts.vapidPublicKey } : {}),
38
+ }),
39
+ )
32
40
 
33
41
  app.get('*', (c) => {
34
42
  const url = new URL(c.req.url)