@indigoai-us/hq-cloud 6.15.0 → 6.15.2
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.
- package/dist/bin/sync-mutation.d.ts +16 -0
- package/dist/bin/sync-mutation.d.ts.map +1 -0
- package/dist/bin/sync-mutation.js +60 -0
- package/dist/bin/sync-mutation.js.map +1 -0
- package/dist/bin/sync-mutation.test.d.ts +2 -0
- package/dist/bin/sync-mutation.test.d.ts.map +1 -0
- package/dist/bin/sync-mutation.test.js +165 -0
- package/dist/bin/sync-mutation.test.js.map +1 -0
- package/dist/bin/sync-runner-company.d.ts +8 -0
- package/dist/bin/sync-runner-company.d.ts.map +1 -1
- package/dist/bin/sync-runner-company.js +16 -0
- package/dist/bin/sync-runner-company.js.map +1 -1
- package/dist/bin/sync-runner-company.test.d.ts +2 -0
- package/dist/bin/sync-runner-company.test.d.ts.map +1 -0
- package/dist/bin/sync-runner-company.test.js +36 -0
- package/dist/bin/sync-runner-company.test.js.map +1 -0
- package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-loop.js +98 -8
- package/dist/bin/sync-runner-watch-loop.js.map +1 -1
- package/dist/bin/sync-runner.d.ts +17 -0
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +109 -0
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/cli/conflict-recovery.test.d.ts +2 -0
- package/dist/cli/conflict-recovery.test.d.ts.map +1 -0
- package/dist/cli/conflict-recovery.test.js +201 -0
- package/dist/cli/conflict-recovery.test.js.map +1 -0
- package/dist/cli/conflict.d.ts +60 -0
- package/dist/cli/conflict.d.ts.map +1 -1
- package/dist/cli/conflict.js +333 -0
- package/dist/cli/conflict.js.map +1 -1
- package/dist/cli/sync.d.ts +35 -0
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +100 -0
- package/dist/cli/sync.js.map +1 -1
- package/dist/cli/sync.test.js +85 -1
- package/dist/cli/sync.test.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/skill-telemetry.d.ts +6 -0
- package/dist/skill-telemetry.d.ts.map +1 -1
- package/dist/skill-telemetry.js +14 -2
- package/dist/skill-telemetry.js.map +1 -1
- package/dist/skill-telemetry.test.js +79 -0
- package/dist/skill-telemetry.test.js.map +1 -1
- package/dist/sync/candidate-uploader.d.ts +88 -0
- package/dist/sync/candidate-uploader.d.ts.map +1 -0
- package/dist/sync/candidate-uploader.js +212 -0
- package/dist/sync/candidate-uploader.js.map +1 -0
- package/dist/sync/candidate-uploader.test.d.ts +2 -0
- package/dist/sync/candidate-uploader.test.d.ts.map +1 -0
- package/dist/sync/candidate-uploader.test.js +132 -0
- package/dist/sync/candidate-uploader.test.js.map +1 -0
- package/dist/sync/delta-client.d.ts +73 -0
- package/dist/sync/delta-client.d.ts.map +1 -0
- package/dist/sync/delta-client.js +201 -0
- package/dist/sync/delta-client.js.map +1 -0
- package/dist/sync/delta-client.test.d.ts +2 -0
- package/dist/sync/delta-client.test.d.ts.map +1 -0
- package/dist/sync/delta-client.test.js +97 -0
- package/dist/sync/delta-client.test.js.map +1 -0
- package/dist/sync/durable-apply.d.ts +76 -0
- package/dist/sync/durable-apply.d.ts.map +1 -0
- package/dist/sync/durable-apply.js +530 -0
- package/dist/sync/durable-apply.js.map +1 -0
- package/dist/sync/durable-apply.test.d.ts +2 -0
- package/dist/sync/durable-apply.test.d.ts.map +1 -0
- package/dist/sync/durable-apply.test.js +180 -0
- package/dist/sync/durable-apply.test.js.map +1 -0
- package/dist/sync/event-sync.d.ts +33 -1
- package/dist/sync/event-sync.d.ts.map +1 -1
- package/dist/sync/event-sync.js +149 -1
- package/dist/sync/event-sync.js.map +1 -1
- package/dist/sync/event-sync.test.js +142 -1
- package/dist/sync/event-sync.test.js.map +1 -1
- package/dist/sync/index.d.ts +2 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +1 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/multipart-uploader.d.ts +99 -0
- package/dist/sync/multipart-uploader.d.ts.map +1 -0
- package/dist/sync/multipart-uploader.js +447 -0
- package/dist/sync/multipart-uploader.js.map +1 -0
- package/dist/sync/multipart-uploader.test.d.ts +2 -0
- package/dist/sync/multipart-uploader.test.d.ts.map +1 -0
- package/dist/sync/multipart-uploader.test.js +119 -0
- package/dist/sync/multipart-uploader.test.js.map +1 -0
- package/dist/sync/mutation-client.d.ts +85 -0
- package/dist/sync/mutation-client.d.ts.map +1 -0
- package/dist/sync/mutation-client.js +245 -0
- package/dist/sync/mutation-client.js.map +1 -0
- package/dist/sync/mutation-client.test.d.ts +2 -0
- package/dist/sync/mutation-client.test.d.ts.map +1 -0
- package/dist/sync/mutation-client.test.js +51 -0
- package/dist/sync/mutation-client.test.js.map +1 -0
- package/dist/sync/push-receiver.d.ts +45 -0
- package/dist/sync/push-receiver.d.ts.map +1 -1
- package/dist/sync/push-receiver.js +101 -0
- package/dist/sync/push-receiver.js.map +1 -1
- package/dist/sync/push-receiver.test.js +54 -2
- package/dist/sync/push-receiver.test.js.map +1 -1
- package/dist/sync/scope-inventory-client.d.ts +69 -0
- package/dist/sync/scope-inventory-client.d.ts.map +1 -0
- package/dist/sync/scope-inventory-client.js +210 -0
- package/dist/sync/scope-inventory-client.js.map +1 -0
- package/dist/sync/scope-inventory-client.test.d.ts +2 -0
- package/dist/sync/scope-inventory-client.test.d.ts.map +1 -0
- package/dist/sync/scope-inventory-client.test.js +94 -0
- package/dist/sync/scope-inventory-client.test.js.map +1 -0
- package/dist/sync/snapshot-client.d.ts +98 -0
- package/dist/sync/snapshot-client.d.ts.map +1 -0
- package/dist/sync/snapshot-client.js +402 -0
- package/dist/sync/snapshot-client.js.map +1 -0
- package/dist/sync/snapshot-client.test.d.ts +2 -0
- package/dist/sync/snapshot-client.test.d.ts.map +1 -0
- package/dist/sync/snapshot-client.test.js +169 -0
- package/dist/sync/snapshot-client.test.js.map +1 -0
- package/dist/sync/uploader-finalization.d.ts +97 -0
- package/dist/sync/uploader-finalization.d.ts.map +1 -0
- package/dist/sync/uploader-finalization.js +273 -0
- package/dist/sync/uploader-finalization.js.map +1 -0
- package/dist/sync/uploader-finalization.test.d.ts +2 -0
- package/dist/sync/uploader-finalization.test.d.ts.map +1 -0
- package/dist/sync/uploader-finalization.test.js +92 -0
- package/dist/sync/uploader-finalization.test.js.map +1 -0
- package/dist/telemetry.d.ts +11 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +21 -2
- package/dist/telemetry.js.map +1 -1
- package/dist/telemetry.test.js +80 -0
- package/dist/telemetry.test.js.map +1 -1
- package/package.json +6 -1
- package/.claude/policies/hq-cloud-esm-cannot-spy-fs-builtins.md +0 -30
- package/.claude/policies/hq-cloud-strip-types-no-parameter-properties.md +0 -22
- package/.github/workflows/ci.yml +0 -84
- package/.github/workflows/publish.yml +0 -56
- package/.github/workflows/unreleased-commits-nag.yml +0 -256
- package/eslint.config.js +0 -67
- package/pnpm-workspace.yaml +0 -2
- package/scripts/presign-transport-e2e.mjs +0 -250
- package/scripts/vault-rebaseline.sh +0 -323
- package/scripts/vault-rescue.sh +0 -332
- package/src/active-company.test.ts +0 -188
- package/src/active-company.ts +0 -168
- package/src/agent-codex-instructions.test.ts +0 -332
- package/src/agent-codex-instructions.ts +0 -309
- package/src/auth.ts +0 -146
- package/src/backup-prune.test.ts +0 -98
- package/src/backup-prune.ts +0 -182
- package/src/bin/backup-prune-runner.ts +0 -33
- package/src/bin/rescue-runner.ts +0 -25
- package/src/bin/sync-runner-company.ts +0 -695
- package/src/bin/sync-runner-events.test.ts +0 -143
- package/src/bin/sync-runner-events.ts +0 -55
- package/src/bin/sync-runner-planning.test.ts +0 -311
- package/src/bin/sync-runner-planning.ts +0 -258
- package/src/bin/sync-runner-rollup.test.ts +0 -37
- package/src/bin/sync-runner-rollup.ts +0 -97
- package/src/bin/sync-runner-telemetry.ts +0 -15
- package/src/bin/sync-runner-watch-loop.ts +0 -1235
- package/src/bin/sync-runner-watch-routes.test.ts +0 -71
- package/src/bin/sync-runner-watch-routes.ts +0 -184
- package/src/bin/sync-runner.test.ts +0 -8767
- package/src/bin/sync-runner.ts +0 -2190
- package/src/cli/accept.ts +0 -124
- package/src/cli/conflict.ts +0 -119
- package/src/cli/doctor.test.ts +0 -581
- package/src/cli/doctor.ts +0 -642
- package/src/cli/index.ts +0 -49
- package/src/cli/invite.test.ts +0 -250
- package/src/cli/invite.ts +0 -214
- package/src/cli/promote.ts +0 -157
- package/src/cli/reindex-knowledge.test.ts +0 -307
- package/src/cli/reindex-knowledge.ts +0 -450
- package/src/cli/reindex.test.ts +0 -957
- package/src/cli/reindex.ts +0 -979
- package/src/cli/rescue-classify-ordering.test.ts +0 -548
- package/src/cli/rescue-clone-diagnostics.test.ts +0 -120
- package/src/cli/rescue-core.ts +0 -3011
- package/src/cli/rescue-drift-reconcile.test.ts +0 -179
- package/src/cli/rescue-drop-dir-symlink.test.ts +0 -224
- package/src/cli/rescue-exec-bit-preserve.test.ts +0 -187
- package/src/cli/rescue-hq-root-guard.test.ts +0 -232
- package/src/cli/rescue-journal-reconcile.test.ts +0 -215
- package/src/cli/rescue-mtime-preserve.test.ts +0 -203
- package/src/cli/rescue-settings-reconcile.test.ts +0 -637
- package/src/cli/rescue-snapshot.test.ts +0 -57
- package/src/cli/rescue-snapshot.ts +0 -51
- package/src/cli/rescue.reindex.test.ts +0 -63
- package/src/cli/rescue.test.ts +0 -131
- package/src/cli/rescue.ts +0 -182
- package/src/cli/share.test.ts +0 -7843
- package/src/cli/share.ts +0 -3663
- package/src/cli/sync-scope.test.ts +0 -652
- package/src/cli/sync.test.ts +0 -5207
- package/src/cli/sync.ts +0 -3470
- package/src/cli/tombstones.ts +0 -106
- package/src/cli/watch-event-push-conflict.test.ts +0 -234
- package/src/client-info.test.ts +0 -214
- package/src/client-info.ts +0 -121
- package/src/cognito-auth.test.ts +0 -712
- package/src/cognito-auth.ts +0 -1422
- package/src/company-resolver.test.ts +0 -618
- package/src/company-resolver.ts +0 -521
- package/src/context.test.ts +0 -583
- package/src/context.ts +0 -378
- package/src/daemon-worker.ts +0 -26
- package/src/daemon.ts +0 -99
- package/src/entity-resolver.test.ts +0 -315
- package/src/entity-resolver.ts +0 -180
- package/src/ignore.test.ts +0 -466
- package/src/ignore.ts +0 -469
- package/src/index.ts +0 -439
- package/src/journal.test.ts +0 -968
- package/src/journal.ts +0 -765
- package/src/lib/cloud-authoritative.test.ts +0 -45
- package/src/lib/cloud-authoritative.ts +0 -59
- package/src/lib/conflict-file.ts +0 -86
- package/src/lib/conflict-index.ts +0 -289
- package/src/lib/conflict.test.ts +0 -348
- package/src/lib/describe-error.test.ts +0 -100
- package/src/lib/describe-error.ts +0 -58
- package/src/lib/exit-codes.ts +0 -24
- package/src/lib/machine-id.test.ts +0 -231
- package/src/lib/machine-id.ts +0 -175
- package/src/lib/net-errors.test.ts +0 -65
- package/src/lib/net-errors.ts +0 -86
- package/src/lib/readlink-safe.test.ts +0 -43
- package/src/lib/readlink-safe.ts +0 -29
- package/src/local-path-codec.test.ts +0 -138
- package/src/local-path-codec.ts +0 -161
- package/src/machine-auth.test.ts +0 -1323
- package/src/manifest-reconcile.test.ts +0 -1123
- package/src/manifest-reconcile.ts +0 -518
- package/src/object-io.test.ts +0 -1221
- package/src/object-io.ts +0 -1306
- package/src/operation-lock.test.ts +0 -484
- package/src/operation-lock.ts +0 -680
- package/src/outcome-telemetry.test.ts +0 -498
- package/src/outcome-telemetry.ts +0 -639
- package/src/personal-vault-exclusions.test.ts +0 -308
- package/src/personal-vault-exclusions.ts +0 -354
- package/src/personal-vault.test.ts +0 -756
- package/src/personal-vault.ts +0 -496
- package/src/prefix-coalesce.test.ts +0 -240
- package/src/prefix-coalesce.ts +0 -273
- package/src/public-surface.test.ts +0 -117
- package/src/qmd-reindex.test.ts +0 -877
- package/src/qmd-reindex.ts +0 -842
- package/src/read-only-state-dir.test.ts +0 -188
- package/src/remote-pull.test.ts +0 -1130
- package/src/remote-pull.ts +0 -618
- package/src/s3.symlink-materialize.test.ts +0 -492
- package/src/s3.test.ts +0 -1789
- package/src/s3.ts +0 -1532
- package/src/schemas/signal-types.test.ts +0 -82
- package/src/schemas/signal-types.ts +0 -38
- package/src/schemas/source-channels.test.ts +0 -82
- package/src/schemas/source-channels.ts +0 -53
- package/src/scope-shrink.test.ts +0 -633
- package/src/scope-shrink.ts +0 -481
- package/src/signals/get.test.ts +0 -310
- package/src/signals/get.ts +0 -75
- package/src/signals/internals.ts +0 -195
- package/src/signals/list.test.ts +0 -420
- package/src/signals/list.ts +0 -79
- package/src/signals/parse.ts +0 -8
- package/src/signals/types.ts +0 -91
- package/src/skill-telemetry.test.ts +0 -1825
- package/src/skill-telemetry.ts +0 -1439
- package/src/sources/get.test.ts +0 -293
- package/src/sources/get.ts +0 -66
- package/src/sources/internals.ts +0 -198
- package/src/sources/list.test.ts +0 -402
- package/src/sources/list.ts +0 -84
- package/src/sources/parse.ts +0 -43
- package/src/sources/types.ts +0 -84
- package/src/sync/event-sync.test.ts +0 -594
- package/src/sync/event-sync.ts +0 -545
- package/src/sync/feature-flags.test.ts +0 -378
- package/src/sync/feature-flags.ts +0 -62
- package/src/sync/index.ts +0 -76
- package/src/sync/lease-client.test.ts +0 -128
- package/src/sync/lease-client.ts +0 -207
- package/src/sync/logger.test.ts +0 -242
- package/src/sync/logger.ts +0 -79
- package/src/sync/metrics.test.ts +0 -462
- package/src/sync/metrics.ts +0 -213
- package/src/sync/pull-scope.ts +0 -265
- package/src/sync/push-event.test.ts +0 -266
- package/src/sync/push-event.ts +0 -224
- package/src/sync/push-receiver.test.ts +0 -566
- package/src/sync/push-receiver.ts +0 -1048
- package/src/sync/push-transport.ts +0 -231
- package/src/sync/realtime-rollout.test.ts +0 -86
- package/src/sync/realtime-rollout.ts +0 -262
- package/src/sync/state-store.test.ts +0 -194
- package/src/sync/state-store.ts +0 -727
- package/src/sync-core.ts +0 -58
- package/src/sync-progress.test.ts +0 -94
- package/src/sync-progress.ts +0 -140
- package/src/telemetry-events.test.ts +0 -88
- package/src/telemetry-events.ts +0 -205
- package/src/telemetry.test.ts +0 -1280
- package/src/telemetry.ts +0 -1109
- package/src/types.ts +0 -314
- package/src/vault-client.test.ts +0 -1380
- package/src/vault-client.ts +0 -1694
- package/src/version.ts +0 -24
- package/src/watch-roots.test.ts +0 -278
- package/src/watch-roots.ts +0 -162
- package/src/watcher-event-gate.test.ts +0 -212
- package/src/watcher.test.ts +0 -1079
- package/src/watcher.ts +0 -1741
- package/test/e2e/sync/cross-tenant-isolation.test.ts +0 -630
- package/test/e2e/sync/skill-telemetry-oversized-transcript.test.ts +0 -124
- package/test/e2e/sync/transient-company-leg.test.ts +0 -384
- package/test/e2e/sync/windows-unreadable-link-leg.test.ts +0 -191
- package/test/e2e/watcher-real-chokidar.test.ts +0 -165
- package/test/e2e/watcher-recursive-backend.test.ts +0 -181
- package/test/e2e/watcher-scoped-coverage.test.ts +0 -381
- package/test/invite-flow.integration.test.ts +0 -244
- package/test/joiner-manifest-reconcile.integration.test.ts +0 -322
- package/test/share-sync.integration.test.ts +0 -213
- package/tsconfig.json +0 -19
- package/vitest.config.ts +0 -22
package/src/sync/push-event.ts
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PushEvent — the wire-shared payload exchanged between every link in the
|
|
3
|
-
* event-driven-hq-cloud-sync pipeline.
|
|
4
|
-
*
|
|
5
|
-
* Producers (the watcher) emit one PushEvent per local content change or
|
|
6
|
-
* delete tombstone.
|
|
7
|
-
* Consumers (the push endpoint / receiver / coalescer) decode the payload,
|
|
8
|
-
* validate it, and act on it. Because the same shape crosses a network
|
|
9
|
-
* boundary, it has its own dedicated module.
|
|
10
|
-
*
|
|
11
|
-
* Conventions
|
|
12
|
-
* ───────────
|
|
13
|
-
* - `kind` is `"upsert"` for content changes and `"delete"` for delete
|
|
14
|
-
* tombstones. Missing `kind` defaults to `"upsert"` for older producers.
|
|
15
|
-
* - `contentHash` is required for upserts and absent for delete tombstones.
|
|
16
|
-
* It is `sha256:<64-lowercase-hex>`. The `<algorithm>:<hex>` prefix lets a
|
|
17
|
-
* future hash migration ship without breaking the wire format — consumers
|
|
18
|
-
* can branch on the prefix and fall back to refusing unknown algorithms.
|
|
19
|
-
* - `mtime` and `eventTimestamp` are strict ISO-8601 datetime strings.
|
|
20
|
-
* `mtime` is the filesystem modification time of the source file at the
|
|
21
|
-
* moment of capture; `eventTimestamp` is when the watcher emitted the
|
|
22
|
-
* event. They diverge whenever the watcher coalesces or retries.
|
|
23
|
-
* - `sequenceNumber` is a non-negative safe integer. Monotonicity per
|
|
24
|
-
* `originDeviceId` is a producer-side invariant — a single PushEvent
|
|
25
|
-
* can't be self-monotonic, so the schema only validates the bounds.
|
|
26
|
-
* - Unknown extra fields are dropped silently by `decodePushEvent` to
|
|
27
|
-
* permit forwards-compatible additions on the producer side without
|
|
28
|
-
* forcing every consumer to upgrade in lockstep.
|
|
29
|
-
*
|
|
30
|
-
* Ported from indigoai-us/hq-pro PR #112 (src/sync/push-event.ts) into
|
|
31
|
-
* @indigoai-us/hq-cloud (Path B) per project event-driven-sync-menubar US-007.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
import { z } from "zod";
|
|
35
|
-
|
|
36
|
-
// ─── Constants ─────────────────────────────────────────────────────────────
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* `sha256:` + 64 lowercase hex chars. The algorithm prefix is mandatory so
|
|
40
|
-
* future hash migrations stay non-breaking; consumers can switch on the
|
|
41
|
-
* prefix and reject unknown algorithms explicitly.
|
|
42
|
-
*/
|
|
43
|
-
export const CONTENT_HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Strict ISO-8601 datetime regex matching what `z.iso.datetime()` produces.
|
|
47
|
-
*
|
|
48
|
-
* Format: `YYYY-MM-DDTHH:MM:SS(.fff)?(Z|±HH:MM)`
|
|
49
|
-
*/
|
|
50
|
-
export const ISO8601_DATETIME_PATTERN =
|
|
51
|
-
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
|
|
52
|
-
|
|
53
|
-
// ─── Zod schema ────────────────────────────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Runtime schema for PushEvent. Unknown extra keys are dropped via the zod
|
|
57
|
-
* default `.strip()` behavior — that is load-bearing for forwards
|
|
58
|
-
* compatibility (see module JSDoc).
|
|
59
|
-
*/
|
|
60
|
-
export const PushEventSchema = z
|
|
61
|
-
.object({
|
|
62
|
-
relativePath: z
|
|
63
|
-
.string()
|
|
64
|
-
.min(1, "relativePath must be a non-empty string"),
|
|
65
|
-
kind: z.enum(["upsert", "delete"]).optional().default("upsert"),
|
|
66
|
-
contentHash: z
|
|
67
|
-
.string()
|
|
68
|
-
.regex(
|
|
69
|
-
CONTENT_HASH_PATTERN,
|
|
70
|
-
"contentHash must match `sha256:<64 lowercase hex>`",
|
|
71
|
-
)
|
|
72
|
-
.optional(),
|
|
73
|
-
mtime: z
|
|
74
|
-
.string()
|
|
75
|
-
.regex(ISO8601_DATETIME_PATTERN, "mtime must be an ISO-8601 datetime")
|
|
76
|
-
.optional(),
|
|
77
|
-
originDeviceId: z
|
|
78
|
-
.string()
|
|
79
|
-
.min(1, "originDeviceId must be a non-empty string"),
|
|
80
|
-
originTenantId: z
|
|
81
|
-
.string()
|
|
82
|
-
.min(1, "originTenantId must be a non-empty string"),
|
|
83
|
-
sequenceNumber: z
|
|
84
|
-
.number()
|
|
85
|
-
.int("sequenceNumber must be an integer")
|
|
86
|
-
.min(0, "sequenceNumber must be non-negative")
|
|
87
|
-
.max(
|
|
88
|
-
Number.MAX_SAFE_INTEGER,
|
|
89
|
-
"sequenceNumber must be <= Number.MAX_SAFE_INTEGER",
|
|
90
|
-
),
|
|
91
|
-
eventTimestamp: z
|
|
92
|
-
.string()
|
|
93
|
-
.regex(
|
|
94
|
-
ISO8601_DATETIME_PATTERN,
|
|
95
|
-
"eventTimestamp must be an ISO-8601 datetime",
|
|
96
|
-
),
|
|
97
|
-
})
|
|
98
|
-
// `.strip()` is the zod 4 default; called explicitly here so the intent is
|
|
99
|
-
// obvious to future readers. Unknown keys MUST NOT throw — see module JSDoc.
|
|
100
|
-
.strip()
|
|
101
|
-
.refine(
|
|
102
|
-
(e) => e.kind === "delete" || (e.contentHash != null && e.mtime != null),
|
|
103
|
-
{ message: "upsert requires contentHash and mtime" },
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* The canonical decoded PushEvent type. `kind` is always present after decode;
|
|
108
|
-
* `contentHash` and `mtime` are present for upserts and absent for deletes.
|
|
109
|
-
*/
|
|
110
|
-
export type PushEvent = z.output<typeof PushEventSchema>;
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Input accepted by the schema. Kept public so encode callers can hand in
|
|
114
|
-
* legacy upsert payloads where `kind` is absent.
|
|
115
|
-
*/
|
|
116
|
-
export type PushEventInput = z.input<typeof PushEventSchema>;
|
|
117
|
-
|
|
118
|
-
// ─── Errors ────────────────────────────────────────────────────────────────
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Public alias for a single decode issue. Aliased here (rather than re-exporting
|
|
122
|
-
* the `$`-prefixed zod internal symbol directly) so consumers can annotate
|
|
123
|
-
* against `PushEventDecodeIssue` without importing zod internals. The alias is
|
|
124
|
-
* structurally identical to `z.core.$ZodIssue`, so this is a non-breaking
|
|
125
|
-
* narrowing of the public surface.
|
|
126
|
-
*/
|
|
127
|
-
export type PushEventDecodeIssue = z.core.$ZodIssue;
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Thrown by `decodePushEvent` (and `encodePushEvent` on invalid input) when
|
|
131
|
-
* the payload fails validation. `.issues` carries the underlying zod issues
|
|
132
|
-
* so callers can render structured diagnostics — see the test suite for an
|
|
133
|
-
* example of asserting on the issue path.
|
|
134
|
-
*/
|
|
135
|
-
export class PushEventDecodeError extends Error {
|
|
136
|
-
readonly issues: readonly PushEventDecodeIssue[];
|
|
137
|
-
readonly stage: "json-parse" | "schema-validation";
|
|
138
|
-
|
|
139
|
-
constructor(
|
|
140
|
-
message: string,
|
|
141
|
-
args: {
|
|
142
|
-
issues: readonly PushEventDecodeIssue[];
|
|
143
|
-
stage: "json-parse" | "schema-validation";
|
|
144
|
-
cause?: unknown;
|
|
145
|
-
},
|
|
146
|
-
) {
|
|
147
|
-
super(message, args.cause === undefined ? undefined : { cause: args.cause });
|
|
148
|
-
this.name = "PushEventDecodeError";
|
|
149
|
-
this.issues = args.issues;
|
|
150
|
-
this.stage = args.stage;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// ─── Encode / Decode ───────────────────────────────────────────────────────
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Validate `event` against `PushEventSchema` and return the canonical JSON
|
|
158
|
-
* serialization. Validating on encode catches producer-side mistakes early
|
|
159
|
-
* (and ensures the output always round-trips through `decodePushEvent`).
|
|
160
|
-
*
|
|
161
|
-
* Extra keys on `event` are dropped — the returned JSON string contains
|
|
162
|
-
* only the declared PushEvent fields.
|
|
163
|
-
*/
|
|
164
|
-
export function encodePushEvent(event: PushEventInput): string {
|
|
165
|
-
const parsed = PushEventSchema.safeParse(event);
|
|
166
|
-
if (!parsed.success) {
|
|
167
|
-
throw new PushEventDecodeError(
|
|
168
|
-
"encodePushEvent: input failed PushEvent schema validation",
|
|
169
|
-
{ issues: parsed.error.issues, stage: "schema-validation" },
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
return JSON.stringify(parsed.data);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Parse and validate an incoming PushEvent. Accepts either a raw JSON string
|
|
177
|
-
* (the on-the-wire form) or an already-parsed object (handy for in-process
|
|
178
|
-
* wiring and tests).
|
|
179
|
-
*
|
|
180
|
-
* - Unknown extra fields are dropped silently — see module JSDoc.
|
|
181
|
-
* - Missing required fields throw `PushEventDecodeError` whose `.issues`
|
|
182
|
-
* exposes the underlying zod issues.
|
|
183
|
-
* - Malformed JSON throws `PushEventDecodeError` with `stage:"json-parse"`
|
|
184
|
-
* and a synthetic issue at the root path.
|
|
185
|
-
* - A JSON string that parses to a non-object value (e.g. `'42'`, `'"text"'`,
|
|
186
|
-
* `'null'`) surfaces as `stage: 'schema-validation'` — the JSON itself was
|
|
187
|
-
* syntactically valid, so it clears the parse stage before failing the
|
|
188
|
-
* object-shape check.
|
|
189
|
-
*/
|
|
190
|
-
export function decodePushEvent(input: unknown): PushEvent {
|
|
191
|
-
let candidate: unknown = input;
|
|
192
|
-
|
|
193
|
-
if (typeof input === "string") {
|
|
194
|
-
try {
|
|
195
|
-
candidate = JSON.parse(input);
|
|
196
|
-
} catch (err) {
|
|
197
|
-
throw new PushEventDecodeError(
|
|
198
|
-
"decodePushEvent: input string is not valid JSON",
|
|
199
|
-
{
|
|
200
|
-
issues: [
|
|
201
|
-
{
|
|
202
|
-
code: "custom",
|
|
203
|
-
message:
|
|
204
|
-
err instanceof Error ? err.message : "invalid JSON input",
|
|
205
|
-
path: [],
|
|
206
|
-
input,
|
|
207
|
-
} as PushEventDecodeIssue,
|
|
208
|
-
],
|
|
209
|
-
stage: "json-parse",
|
|
210
|
-
cause: err,
|
|
211
|
-
},
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const parsed = PushEventSchema.safeParse(candidate);
|
|
217
|
-
if (!parsed.success) {
|
|
218
|
-
throw new PushEventDecodeError(
|
|
219
|
-
"decodePushEvent: payload failed PushEvent schema validation",
|
|
220
|
-
{ issues: parsed.error.issues, stage: "schema-validation" },
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
return parsed.data;
|
|
224
|
-
}
|